Pregunta

¿Cómo puedo crear un método en el @implementation de una clase sin definirlo en el @interface?

Por ejemplo, tengo un constructor que hace algo de inicialización y luego lee datos de un archivo. Quiero factorizar el código del archivo de lectura en un método independiente que luego me llamo desde dentro del constructor. No quiero definir este método en la cabecera porque es privada sólo a este contexto @implementation.

¿Es esto posible?

Aquí está mi ejemplo. Tengo un pequeño programa que lee una lista de tareas Todo desde un archivo.

Aquí es el @interface:

@interface TDTaskList : NSObject {
  NSString* name; // The name of this list.
  NSMutableArray* tasks;  // The set of tasks in this list.
}

-(id)initListOfName:(NSString*)aName;
-(NSArray*)loadListWithName:(NSString*)aName;

@end

Y aquí es parte de la @implementation:

-(id)initListOfName:(NSString*)aName {
  if (self = [super init]) {
    name = aName;

    NSArray* aTasks = [self loadListWithName:aName];
    tasks = [NSMutableArray arrayWithArray:aTasks];
  }

  return self;
}

-(NSArray*)loadListWithName:(NSString*)aName {
  // TODO This is a STUB till i figure out how to read/write from a file ...

  TDTask* task1 = [[TDTask alloc] initWithLabel:@"Get the Milk."];
  TDTask* task2 = [[TDTask alloc] initWithLabel:@"Do some homework."];

  return [NSArray arrayWithObjects:task1, task2, nil];
}

Lo que quiero hacer es no que definir lo siguiente en la interfaz:

-(NSArray*)loadListWithName:(NSString*)aName;
¿Fue útil?

Solución

Si coloca la implementación de un método antes de cualquier código que llama no es necesario definirlo en la cabecera.

Así que en este caso poner loadListWithName: frente a initListOfName:. en el bloque @implementation y que será bueno

Nota: El hecho de que no se define en la cabecera no significa que el método no puede ser llamado por el código fuera del objeto. Objective-C no tiene métodos privados.

Otros consejos

Cuando Andy dio a entender en los comentarios, puede utilizar Extensiones (que parecen una categoría sin un nombre). La diferencia es que debe poner en práctica los métodos declarados en una extensión mientras que el compilador no comprueba que implemente métodos declarados en una categoría.

.h:

@interface MyObject : NSObject
{
    NSNumber *number;
}
- (NSNumber *)number;
@end

.m:

@interface MyObject ()
- (void)setNumber:(NSNumber *)newNumber;
@end

@implementation MyObject

- (NSNumber *)number
{
    return number;
}
- (void)setNumber:(NSNumber *)newNumber
{
    number = newNumber;
}
@end

Se puede usar categorías :

// In TDTaskList.m
@interface TDTaskList(TDTaskListPrivate)
-(id)initListOfName:(NSString*)aName;
-(NSArray*)loadListWithName:(NSString*)aName;
@end

@implementation TDTaskList(TDTaskListPrivate)

// implementation of initListOfName and loadListWithName ...

@end

Existen dos opciones razonables. Ambos fueron básicamente ya se ha descrito, pero en mi humilde opinión eran un poco claro o incluso simplemente erróneo.

Las categorías no son uno de ellos, ya que están pensadas para que yo sepa el propósito completamente diferente de romper implementaciones en múltiples archivos de origen.

  • Haz lo que Nathan ha descrito anteriormente. A pesar de que está mal con su última hipótesis (métodos privados).
  • Utilice una definición de extensión método privado para permitir el avance referencia de la siguiente manera:

    1. eliminar la definición de loadListWithName desde su cabecera por completo
    2. añadir lo siguiente en la fuente (.m) antes del bloque @implementation
    @interface TDTaskList (PrivateMethods)
    -(NSArray*)loadListWithName:(NSString*)aName;
    @end
    
    @implementation ...
    

  • Licenciado bajo: CC-BY-SA con atribución
    No afiliado a StackOverflow
    scroll top