2013-09-10 4 views
1

компании Apple рекомендует вам получить доступ к переменные экземпляра, которые поддерживают свои свойства напрямую, а не с помощью геттер/сеттер, при инициализации класса:Инициализация Objective C свойство в дочернем классе

https://developer.apple.com/library/ios/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html

Тем не менее, кажется, переменные экземпляра, поддерживающие свойство в родительском классе, недоступны в дочернем классе; Почему это так? Я расширяю класс в библиотеке (Cocos2d), где не все переменные экземпляра инициализируются в функции init родительского класса. Например:

--- 

@interface parentClass 

@property (assign) int myProperty; 

---- 

@interface childClass : parentClass 

---- 

@implementation childClass 

- (id) init { 
    // this doesn't work. 
    _myProperty = 0; 
} 
+2

'@ property' с префиксом подчеркивания в классах, я думаю, вы должны написать' _myProperty = 0; ' – DCMaxxx

+1

Попробуйте _myProperty – Rog

+0

Возможно, вы не знаете имя свойства ivar, используемое при имплантации суперкласса. Затем вы можете инициализировать с self.propertyname = – uchuugaka

ответ

2

Вы не можете получить доступ к переменным экземпляра из вашего суперкласса в подклассе, так _variableName также не работает.

Вы init метод будет выглядеть примерно так

- (instancetype)init { 
    if (self=[super init]) { 
     // subclass initialisation goes here 
    } 
} 

После [super init] возвращается объект, суперкласс часть вашего объекта инициализируется, поэтому он должен быть безопасным доступ к свойствам, используя свои методы получения и установки:

- (instancetype)init { 
    if (self=[super init]) { 
     self.superClassProperty = aValue; 
    } 
} 

Обратите внимание на то, когда следует использовать переменные экземпляра и методы вызова (например, средства доступа к свойствам). Короче: только вызовы, когда ваш объект находится в согласованном состоянии.

Почему вы не можете получить доступ к иварам?

Объявление свойства в заголовке объявляет getter и setter для свойства, при создании свойства создается инициал ivar, который происходит в реализации. (Автоматический и ручной синтез не имеет значения). Декларация ivar для этого только видна в реализации. Если вам абсолютно необходимо получить доступ к ivars в подклассах, вы должны сделать их общедоступными (или полупубличными, помещая их в заголовок только для подкласса).

+0

Позвольте пояснить. Кажется, я могу получить доступ к экземплярам переменных в некоторых случаях, например, если в реализации родительского класса свойство синтезируется и явно поддерживается (@synthesize myProperty = _myProperty). Это верно? – Peter

+0

Нет, я отредактирую свое сообщение, чтобы уточнить – Sebastian

+0

Спасибо.Теперь я понимаю общее сообщение, что я должен использовать только геттеры и сеттеры, когда объект находится в согласованном состоянии. Тем не менее, я просто смущен тем, почему я МОЖЕТ (не должен) иногда обращаться к переменным экземпляра родителя в дочернем классе. Чтобы дать вам пример из библиотеки Cocos2d, класс CCParticleMeteor в CCParticleExamples.m обращается к переменной экземпляра _startColor в методе initWithTotalParticles :, но эта переменная экземпляра объявлена ​​в CCParticleSystem, которая является прародителем этого класса. – Peter

0

Вы можете сделать следующее в вашем parentClass.h:

@interface parentClass { 
    @protected 
    int _myProperty; 
} 
@property (nonatomic) int myProperty; 

Тогда в вашем childClass.m

- (instancetype)init { 
    if (self=[super init]) { 
     _myProperty = aValue; 
    } 
} 

Иварс объявлены как защищенные по умолчанию, так что ваши дети могут увидеть их , Нет необходимости писать @protected. И для вашей информации вы также можете объявить их как @private или @public.

Но если вы напишете защищенный iVar в частном интерфейсе в родительском классе, это не сработает, и дети его не увидят.

Смежные вопросы