Objective-C-实例变量与属性的关系

时间:2023-12-09 23:22:43

当在一个类创建一个属性,Xcode编译器就会自动产生一个带下划线的同名实例变量;

一般来说,如果getter这个属性采用下划线的方式获取效率更高,而setter采用self.属性名更加合理。

读取实例变量的时候采用直接访问的形式,而在设置实例变量的时候通过属性来做。

直接访问实例变量时,不会调用其“设置方法”,也就是说不会不会触发“键值观测”(Key-Value Observing, KVO)通知。


第一个要注意的地方就是,在初始化方法中应该如何设置属性值。这种情况下总是应该直接访问实例变量,因为子类可能会“覆写”(override)设 置方法。假设EOCPerson有一个子类叫做EOCSmithPerson,这个子类专门表示那些姓“Smith”的人。该子类可能会覆写 lastName属性所对应的设置方法:

  1. - (void)setLastName:(NSString*)lastName {
  2. if (![lastName isEqualToString:@"Smith"]) {
  3. [NSException raise:NSInvalidArgumentException
  4. format:@"Last name must be Smith"];
  5. }
  6. self.lastName = lastname;
  7. }

在基类EOCPerson的默认初始化方法中,可能会将姓氏设为空字符串。此时若是通过“设置方法”来做,那么调用的将会是子类的设置方法,从而抛 出异常。但是,某些情况下却又必须在初始化方法中调用设置方法:如果待初始化的实例变量声明在超类中,而我们又无法在子类中直接访问此实例变量的话,那么 就需要调用“设置方法”了。

另外一个要注意的问题是“惰性初始化”(lazy initialization)。在这种情况下,必须通过“获取方法”来访问属性,否则,实例变量就永远不会初始化。比方说,EOCPerson类也许会 用一个属性来表示人脑中的信息,这个属性所指代的对象相当复杂。由于此属性不常用,而且创建该属性的成本较高,所以,我们可能会在“获取方法”中对其执行 惰性初始化:

  1. - (EOCBrain*)brain {
  2. if (!_brain) {
  3. _brain = [Brain new];
  4. }
  5. return _brain;
  6. }

若没有调用“获取方法”就直接访问实例变量,则会看到尚未设置好的brain,所以说,如果使用了“惰性初始化”技术,那么必须通过存取方法来访问brain属性。