1

Apple 建议您在初始化类时直接访问支持属性的实例变量,而不是使用 getter/setter:

https://developer.apple.com/library/archive/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;
}
4

2 回答 2

2

您无法从子类中的超类访问实例变量,因此_variableName也不起作用。

init的方法看起来像这样

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

一旦[super init]返回一个对象,对象的超类部分就会被初始化,因此使用它们的 getter 和 setter 访问属性应该是安全的:

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

查看QualityCoding 上的“Don't message self in Objective-C init”,了解何时使用实例变量以及何时调用方法(例如属性访问器)。简而言之:仅当您的对象处于一致状态时才调用方法。

为什么你不能访问支持 ivars?

标头中的属性声明为属性声明了一个 getter 和 setter,在综合属性时创建一个支持 ivar,这发生在实现中。(自动和手动合成没有区别)。因此,ivar 声明仅在实现中可见。如果您绝对必须访问子类中的 ivars,则必须将它们公开(或半公开,将它们放在仅用于子类化的标头中)。

于 2013-09-10T00:59:14.100 回答
0

您可以在 parentClass.h 中执行以下操作:

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

然后,在你的 childClass.m

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

iVar 默认声明为受保护,因此您的孩子可以看到它们。不需要写@protected。为了您的信息,您还可以将它们声明为@private 或@public。

但是,如果您在 parentClass.m 中的私有接口中编写受保护的 iVar,这将不起作用,孩子也不会看到它。

于 2016-01-29T13:44:43.327 回答