前提
对以下内容的理解请谨记Objective-C很重要的的一个特性:消息传递。众所周知,在OC中我们使用[]“调用一个对象的方法”,但实际上这里使用“调用”是不准确的,更加严谨的理解是,我们是向该对象发送了一条消息,例如[object doSomething];
这会使OC在运行时向object发送一条消息,而object对象便会在实现文件里匹配一个名字叫做doSomething的方法,如果这时候实现文件不存在名称为doSomething的无参方法,程序运行就会出错。有则执行这个方法。另外一个比较常用的是在OC 2.0以后,OC引进了“点语法”的特性,允许我们像C++,java一样通过“对象.属性”的形式来访问对象的属性,而没有必要再像从前一样使用[object 属性名]
访问属性,使用[object set属性名]
修改属性。但这里我们需要知道的是,虽然我们使用点语法来访问修改属性,但OC运行时执行的依旧还是属性对应的“存取方法”,只是有些时候,编译器在编译阶段自动帮我们生成了属性对应的存取方法。
把实例变量声明在{}
把实例变量声明在{}引发的问题
请看以下代码
@interface MyObject : NSObject{
NSString *firstName;
NSString *lastName;
}
@end
@implementation MyObject
@end
以上的MyObject类在{}里声明了两个实例变量。此时,你可以在类内通过“实例变量名”来访问该实例变量,如
firstName = @"myName";
lastName = firstName;
但是你不能使用诸如
//类内访问
[self firstName]
[self setFirstName]
//类外访问
[object firstName]
[object setFirstName]
来访问实例变量。因为这种情况下编译器是不会帮你自动生成这两个实例变量对应的“存取方法”的。同样的原因,你也无法通过“点语法”:
//类内
self.firstName
//类外
object.firstName
来访问实例变量。因为“点语法”最后也会转换成消息传递来实现的(前文已说明)。
解决把实例变量声明在{}引发的问题
知道了问题的本质,要解决以上的问题,自然是在类中把实例变量的“存取方法”的声明(头文件)和实现(实现文件)写出来就好。
@property关键字
@property关键字的引入,就可以很方便的让编译器知道它需要自动生成相应实例变量的“存取方法”,并生成名为_属性名
的实例变量。在这里也可以得到一个结论:属性 最终还是通过实例变量来实现的。还是直接上代码:
@interface MyObject : NSObject{
}
@property NSString *firstName;
@property NSString *lastName;
@end
@implementation MyObject
@end
这种情况下就可以正常使用以上方法访问实例变量(属性)了:
//类内访问
[self firstName]
[self setFirstName]
self.firstName //点语法
//类外访问
[object firstName]
[object setFirstName]
object.firstName //点语法
另外如果使用了readonly
关键字,编译器只会自动生成get方法,不会生成set方法。
题后话
@property除了有本文所讨论的作用,在内存管理还有很大的作用,因有些同学会疑惑类变量应该声明在哪里,本文只讨论一下这个问题,其他小编就不延伸了。