mutableCopyWithZone запутанное требование?

Пояснение: вопрос не в мутабельности, а в неизменяемости, а в вызове супер-создания экземпляра правильного класса. Я не думал об использовании [[self class] alloc] в базовом классе, и это, кажется, решить мои проблемы. Я приму этот ансер в ближайшие несколько часов, если ничего лучше не придет:)


Спецификация Apple гласит:

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 экземплярам нужно больше места для своих собственных иваров.

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

1 ответ

Решение

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

Проблема возможна, если метод super (или метод super super и т. Д.) Не реализует создание объекта надлежащим образом:

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

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

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

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

Другие вопросы по тегам