Как мне расширить NSArray? - PullRequest
6 голосов
/ 23 января 2012

Вот моя попытка:

H файл:

@interface Strings : NSArray
@end

М файл:

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

Когда я бегу, я получаю это:

'NSInvalidArgumentException', причина: '* - [NSArray initWithObjects: count:]: метод, определенный только для абстрактного класса Определить - [Строки initWithObjects: count:]! '

Это то, что я сделал вместо этого:

H файл:

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

М файл:

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

Ответы [ 5 ]

8 голосов
/ 23 января 2012

NSArray - это кластер класса (ссылка на документацию Apple) .Это означает, что при попытке создать NSArray система создает некоторый закрытый подкласс NSArray.Класс NSArray просто определяет интерфейс;подклассы NSArray обеспечивают реализации интерфейса.

Вы можете написать свой собственный подкласс NSArray, но вы должны предоставить свое собственное хранилище для объектов в массиве.Вы должны инициализировать это хранилище самостоятельно.Сообщение об ошибке говорит вам об этом, говоря, что вам нужно переопределить initWithObjects:count: в вашем подклассе.Ваше переопределение должно поместить объекты в любое хранилище, которое вы выделите как часть реализации вашего класса.

Реализация NSArray метода variadic initWithObjects: - это просто оболочка вокруг initWithObjects:count:, так что вы ненужно реализовать initWithObjects:.

5 голосов
/ 23 января 2012

Получение от NSArray - это то, чего вам следует избегать. Из документации:

Помните, что NSArray является общедоступным интерфейсом для кластера классов и что это влечет за собой для вашего подкласса. Примитивные методы NSArray не включают никаких назначенных инициализаторов. Это означает, что вы должны предоставить хранилище для вашего подкласса и реализовать примитивные методы, которые непосредственно воздействуют на это хранилище.

Это означает, что при инициализации массива вы не получаете экземпляр NSArray. Вы получите экземпляр совершенно другого класса, который просто имеет тот же интерфейс. Вот почему создание подклассов не работает так, как вы думаете: вы должны полностью реализовать хранилище самостоятельно. Вот почему в документации говорится:

Любой подкласс NSArray должен переопределять примитивные методы экземпляра count и objectAtIndex :. Эти методы должны работать с резервным хранилищем, которое вы предоставляете для элементов коллекции. Для этого резервного хранилища вы можете использовать статический массив, стандартный объект NSArray или какой-либо другой тип данных или механизм. Вы также можете переопределить, частично или полностью, любой другой метод NSArray, для которого вы хотите предоставить альтернативную реализацию.

И последнее, но не менее важное: у вас в любом случае была бы неправильная инициализация. Вам нужно было бы позвонить super:

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

    return self;
}

Но, как я только что сказал, это не так легко работает. Вы получите то же самое исключение снова. Так что вам следует просто избегать производных от NSArray.

Что вы можете сделать - это добавить категорию для добавления методов ко всем NSArray экземплярам.

2 голосов
/ 23 января 2012

NSArray не поддерживает подклассы таким образом. Вы можете добавить категорию, хотя это не всегда рекомендуется.

См. Цель C - Подклассы NSArray для получения дополнительных мыслей.

1 голос
/ 23 января 2012

Вам нужно присвоить себя и вызвать метод init вашего суперкласса.

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

return self;
1 голос
/ 23 января 2012

возможно

self = [super initWithObjects:...];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...