Редактировать: Я только что заметил этот другой вопрос о переполнении стека, который задает примерно то же самое: Почему подкласс @property без соответствующего ivar скрывает ivars суперкласса?
Это интересное поведение, которое я не могу найти документированным ни в чем официальном или неофициальном (блог, твит, вопрос SO и т. Д.). Я свел его к сути и проверил в новом проекте Xcode, но я не могу его объяснить.
MyBaseClass имеет переменную экземпляра:
@interface MyBaseClass : NSObject {
NSObject *fooInstanceVar;
}
@end
MySubclass расширяет MyBaseClass и объявляет совершенно несвязанное свойство (то есть , свойство не предназначено для поддержки переменной экземпляра):
#import "MyBaseClass.h"
@interface MySubclass : MyBaseClass { }
@property (nonatomic, retain) NSObject *barProperty;
@end
Если реализация MySubclass не синтезирует свойство, но реализует методы доступа, все в порядке (без ошибок компилятора):
#import "MySubclass.h"
@implementation MySubclass
- (NSObject*)barProperty {
return [[NSObject alloc] init]; // pls ignore flagrant violation of memory rules.
}
- (void)setBarProperty:(NSObject *)obj { /* no-op */ }
- (void)doSomethingWithProperty {
NSArray *array = [NSArray arrayWithObjects:self.barProperty, fooInstanceVar, nil];
NSLog(@"%@", array);
}
@end
Но если я удалю методы доступа к свойству и заменю их объявлением synthesize
для свойства, я получу ошибку компилятора: 'fooInstanceVar' undeclared (первое использование в этой функции)
.
#import "MySubclass.h"
@implementation MySubclass
@synthesize barProperty;
- (void)doSomethingWithProperty {
NSArray *array = [NSArray arrayWithObjects:self.barProperty, fooInstanceVar, nil];
NSLog(@"%@", array);
}
@end
Эта ошибка исчезнет, если я удалю либо объявление synthesize
, либо если я не буду ссылаться на переменную экземпляра fooInstanceVar
из MySubclass.m, либо если я поставлю все определения интерфейса и реализации в одном файле. Эта ошибка также возникает в настройках сборки GCC 4.2 и GCC / LLVM.
Кто-нибудь может объяснить, что здесь происходит?