Редактировать: Я только что заметил этот другой вопрос переполнения стека, задающий почти то же самое: Почему подкласс @property без соответствующего ivar скрывает суперкласс ivar?
Это интересное поведение, которое я не могу найти ни в одном официальном или неофициальном документе (блог, твит, вопрос SO и т. Д.).Я довел его до сути и протестировал в новом проекте XCode, но не могу объяснить это.
У MyBaseClass есть переменная экземпляра:
@interface MyBaseClass : NSObject {
NSObject *fooInstanceVar;
}
@end
MySubclass extends 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.
Кто-нибудь может объяснить, что здесь происходит?