2013-05-29 5 views
0

Уточнение: вопрос не о изменчивом и неизменяемом, а о вызове super, создающем экземпляр правильного класса. Я не думал использовать [[self class] alloc] в базовом классе, и это, похоже, решает мои проблемы. Я принимаю, что AnSer в ближайшие несколько часов, если ничего лучше не приходит :)mutableCopyWithZone непонятное требование?


The Apple spec says:

If a subclass inherits NSMutableCopying from its superclass and declares 
additional instance variables, the subclass has to override mutableCopyWithZone: 
to properly handle its own instance variables, invoking the superclass’s 
implementation first. 

Это очень сбивает с толку. Рассмотрите

@interface Base : NSObject<NSMutableCopying> 
@property (nonatomic, assign) NSInteger value ; 
@end 
@implementation Base 
... 
@end 


@interface Derived : Base<NSMutableCopying> 
@property (nonatomic, assign) NSInteger value2 ; 
@end 

@implementation Derived 

- (id) mutableCopyWithZone: (NSZone *) zone { 
    // Huh ??? 
    Derived * derived = [super mutableCopyWithZone: zone] ; 
    ... 
    // Huh ?????? 
    derived.value2 = self.value2 ; 
    return derived ; 
} 
... 
@end 

Я просто не понимаю, как этот код может быть прав, если я следую спецификации.

Когда звонок в [super mutableCopyWithZone: zone] возвращается, я ожидаю, что базовый класс выделил достаточно места для своих собственных иваров. Нельзя сказать, что экземпляры Derived нуждаются в большем количестве для своих собственных иваров.

В чем заключается документация? Как мне это реализовать?

+0

В соответствии с документацией только классы, которые определяют различие «неизменяемого и изменяемого», должны принимать протокол NSMutableCopying. У вас есть как «Derived», так и «MutableDerived»? –

+0

Я думаю, что Derived - это изменяемый класс, а base - неизменный класс. –

+1

Если Base был непреложным классом, тогда он не принял протокол NSMutableCopying. –

ответ

4

super только изменяет способ отправки (статический, а не динамический). Но он не меняет приемник, особенно. он не поднимается. В -mutableCopyWithZone: (супер) self все еще указывает на экземпляр объекта производного класса.

Trouble возможно, если супер метод (или супер супер метод и так далее) не реализует создание объекта в надлежащем порядке:

copy = [[BaseClass alloc] init]; // Wrong, an instance of the base class is created 

copy = [[[self class] alloc] init]; // Correct, an instance of [self class] == DerivedClass is created 

Используя второй подход, вы получите экземпляр производных класс с полной памятью для своих иваров.

Заключение: реализуйте его таким образом, если BaseClass реализует свой -mutableCopyWithZone: правильно. В противном случае у вас нет других изменений, кроме создания собственной копии и ее инициализации.

В моих книгах я всегда пишу, что нет оснований использовать имя класса внутри класса. Использование [self class] (в методе экземпляра) и self (в методе класса) на 99% лучше подходит.

+1

Но что, если вызов 'mutableCopy' объекта' Derived' должен возвращать объект 'MutableDerived' (сравнить мой комментарий к вопросу), например NSString и NSMutableString? - Я не уверен, как это будет работать с подклассом. –

+1

Во-первых: я не думаю, что его вопрос указывает на особую проблему с mutableCopy, но и для копирования.(И любая другая ситуация, в которой экземпляр должен быть создан методом базового класса (например, new, который помечен в NSObject, но создает экземпляры кэша приемника). Second: В вашем случае экземпляр Производится, потому что сообщение отправлено в Derived и [[self class] alloc] (ImmutableBase) создаст экземпляр Derived. Все в порядке. В-третьих: Если -mutableCopy (без WithZone :) отправляется в ImmutableBase, ImmutableBase «знает» о своем подклассе –

+1

Не поймите меня неправильно: я считаю, что ваш ответ верен для протокола NSCopying. - Я имел в виду: отправка 'mutableCopy' в экземпляр' Derived' должен возвращать 'MutableDerived' Как может реализация базового класса справиться с этим? - Интересно, как NSMutableCopying и подклассов вообще работают вместе (класс «MutableDerived» не может быть подчинен класс «Derived» и «MutableBase» ... - но это, вероятно, другой вопрос :-) –