Custom getters and setters 自定义 getter 和 setter

我们只会在两种情况里,需要直接获取实例变量,第一种是当你需要自定义 get 和 set 访问器的时候。默认情况下,属性自带的访问器方法,是可以读写实例变量的,但是你想用自定义它们。 比如说当属性发生变化的时候,你想要把数据写入文件里,这时候就可以用到自定义 get 和 set 访问器。

重写访问器也是理解合成实例变量过程的好方法,能帮我们进一步理解 Objective-C 的属性。

现在我们用下面的代码,放到 Person.m 里:

@implementation Person
@synthesize name = _name;
- (void)printGreeting {
    NSLog(@"Hello, %@!", self.name);
}
- (NSString*)name {
    NSLog(@"Reading name!");
    return _name;
}
- (void)setName:(NSString *)newName {
    NSLog(@"Writing name!");
    _name = newName;
}

这段代码做的第一件事情,就是把属性合成为 _name 实例变量,这是 Xcode 自己完成的,但是由于你想重写这个方法,这一步就需要自己完成。get 和 set 这两个访问器方法的名字一定要这样写,并且你必须返回和这个属性相同的数据类型。不要担心记不住啦,Xcode 的自动补全超好用的。ʅ(‾◡◝)

我之前说过,这种方法是非常适合直接获取实例变量的,name 方法返回_name,setName 方法来直接设定这个值。其实在这里,已经不仅仅是「适合」的问题了,而是「必须」这么做。

如果我们在 setName 方法里面写的是 self.name,那么 self.name 就会调用 setName 方法,而 setName 方法又会再去设定 self.name,它会一直循环循环循环,直到程序崩溃。

现在,你已经自定义好了你的访问器方法,并且把每一步都打印出来了,来看看他是怎么在背后运行的。运行这段代码,你会一次看到先后出现了:"Writing name!", "Reading name!", "Hello, Taylor!" 。

好,我们现在试着这样来写 printGreeting 方法:

- (void)printGreeting {
    NSLog(@"Hello, %@!", _name);
}

这样代码就会直接访问实例变量,而不是使用属性方法,所以这里只会打印出"Hello Taylor!",没有前面的内容了。

很多人会觉得直接用实例变量就好了,尤其是在他们觉得安全的情况下,但是这通常都是 flag……

所以,除了在自定义get 和 set 这两个访问器的时候是必须要直接用实例变量,其他地方一定要慎重使用。

results matching ""

    No results matching ""