Изменить: Я просто заметил, что этот другой вопрос задал одно и то же: Почему подкласс @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 (first use in this function)
.
#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.
Может ли кто-нибудь объяснить, что происходит здесь?