2012-01-22 14 views
6

Aquí está mi intento: archivo¿Cómo extiendo un NSArray?

H:

@interface Strings : NSArray 
@end 

archivo M:

@implementation Strings 
- (id) init 
{ 
    [self initWithObjects: 
    @"One.", 
    nil]; 
    return self; 
} 
@end 

Cuando corro me sale esto:

'NSInvalidArgumentException', razón: '* - [NSArray initWithObjects: count:]: método solo definido para la clase abstracta. Definir - [Strings initWithObjects: count:]! '

Esto es lo que hice en su lugar:

archivo H:

archivo
@interface Strings : NSObject 
+ (NSArray*) getStrings; 
@end 

M:

@implementation Strings 
+ (NSArray*) getStrings 
{ 
    NSArray* strings = [[NSArray alloc] initWithObjects: 
    @"One.", 
    nil]; 
    return strings; 
} 
@end 

Respuesta

8

NSArray es un class cluster (link to Apple's documentation). Esto significa que cuando intenta crear un NSArray, el sistema crea alguna subclase privada de NSArray. La clase NSArray solo define una interfaz; las subclases de NSArray proporcionan implementaciones de la interfaz.

Puede escribir su propia subclase de NSArray, pero debe proporcionar su propio almacenamiento para los objetos de la matriz. Debe inicializar ese almacenamiento usted mismo. El mensaje de error te dice esto, diciendo que necesitas sobrescribir initWithObjects:count: en tu subclase. Su reemplazo tiene que colocar los objetos en el almacenamiento que asigne como parte de la implementación de su clase.

El NSArray implementación del método variadic initWithObjects: es sólo una envoltura alrededor de initWithObjects:count:, por lo que no tiene que poner en práctica initWithObjects:.

+1

Además, asegúrese de leer y ** comprender ** la sección "Notas de subclases" del * [Referencia de la clase NSArray] (http://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/ Classes/NSArray_Class/NSArray.html # // apple_ref/doc/uid/20000137-740795) * antes de escribir su propia subclase 'NSArray'. –

2

NSArray no soporta ser una subclase de esta manera. Puede agregar una categoría, aunque eso no es universalmente recomendado.

Consulte Objective C - Subclassing NSArray para más ideas.

+0

me cambiaron a auto = [initWithObjects asistencia: pero eso no ayudó. –

+0

Supongo que podría ser que [NSArray alloc] no asigne realmente un NSArray, así que cuando lo haga, no habrá implementación. ¡Ayuda! Pero ¿por qué continúa con initWithObjects: count:? –

+0

¿Por qué crees que necesitas subclase NSArray de todos modos? A menos que esté haciendo una tienda de respaldo especializada, generalmente no es un buen enfoque. – StilesCrisis

1

quizá

self = [super initWithObjects:...]; 
+0

Eso es cierto, pero la subclasificación de NSArray en específico también tiene reglas especiales. – StilesCrisis

+0

Es cierto. Bueno, dejaré la respuesta, no obstante. Lo primero es lo primero. –

+0

@StilesCrisis, y obtienes mi voto positivo :) –

1

necesita asignar uno mismo, y llamar al método init sus superclase.

if (self = [super initWithObjects:...]) { 
    ... 
} 

return self; 
+0

Eso es cierto, pero la subclasificación de NSArray en específico también tiene reglas especiales. – StilesCrisis

5

Deriva de NSArray es algo que debe evitar. De la documentación:

Recuerde que NSArray es la interfaz pública para un clúster de clase y lo que esto conlleva para su subclase. Los métodos primitivos de NSArray no incluyen ningún inicializador designado. Esto significa que debe proporcionar el almacenamiento para su subclase e implementar los métodos primitivos que actúan directamente sobre ese almacenamiento.

Lo que esto significa es que cuando inicializa una matriz, no obtiene una instancia de NSArray. Obtendrá una instancia de una clase totalmente diferente que simplemente tiene la misma interfaz. Es por eso que la creación de subclases no funciona de la manera que usted cree que funciona: tendrá que implementar completamente el almacenamiento usted mismo. Esta es la razón por la cual la documentación además establece:

Cualquier subclase de NSArray debe anular el recuento de métodos de la instancia primitiva y objectAtIndex :. Estos métodos deben operar en la tienda de respaldo que proporcione para los elementos de la colección. Para esta tienda de respaldo puede usar una matriz estática, un objeto NSArray estándar o algún otro tipo de datos o mecanismo. También puede elegir anular, parcial o totalmente, cualquier otro método NSArray para el que desee proporcionar una implementación alternativa.

Por último, la inicialización habría sido incorrecta de todos modos.Usted habría necesitado para llamar super:

- (id)init 
{ 
    self = [super initWithObjects:@"One", @"Two", nil]; 
    if (!self) return nil; 

    return self; 
} 

Pero como acabo de decir, simplemente no funciona tan fácilmente. Obtendrá la misma excepción nuevamente. Por lo tanto, simplemente debe evitar derivar de NSArray.

Lo que puede hacer es agregar una categoría para agregar métodos a todas las instancias de NSArray.

Cuestiones relacionadas