第六条 “属性”概念

理解“属性”概念

"属性"(property),是Objective-C的一项特性,用于封装对象中的数据。OC对象通常会把其所需要的数据保存为各种实例变量,实例变量一般通过“存取方法”来访问。“属性”这一特性已经成为OC的一部分,开发者可以令编译器自动编写与属性相关的存取方法。此特性引入了“点语法”。

问题来源

再描述个人信息的类中,也许会存放人民、生日、地址等内容,可以在类接口的public区段中声明一些实例变量

@interface EOCPerson : NSobject
@public
    NSString *_firstName;
    NSString *_lastName;
@private
    NSString *_someInternalData;
@end

在这种写法中,可以定义实例变量的作用域,然而编写Objective-C代码是却很少这么做。这种写法的问题是:对象布局在编译期就已经固定了。只要碰到访问_firstName变量的代码,编译器就把其替换为“偏移量”。这个偏移量是“硬编码”,表示该变量距离存放对象的内存区域的起始位置有多远。如果又加入了一个实例变量。例如,在firstName之前再加一个。

@interface EOCPerson : NSobject
@public
    NSDate *_dateOfBirth;
    NSString *_firstName;
    NSString *_lastName;
@private
    NSString *_someInternalData;
@end

原来表示_firstName的偏移量现在却指向_dateOfBirth了,把偏移量硬编码与其中的那些代码都会读取到错误的值。

如果代码使用了编译期计算出来的偏移量,那么在修改类定义之后必须重新编译,否则就会出错。

OC的做法是,把实例变量当作一种存储偏移量所用的“特殊变量”,交由“类对象”保管。偏移量会在运行期查找,如果类的定义变了,那么存储的偏移量也就变了,这样的话,无论何时访问实例变量。总能使用正确的偏移量。甚至可以在运行期向类中新增实例变量,这就是稳固的“应用程序二进制接口”(Application Binary Interface,ABI)。ABI定义了许多内容,其中一项就是生成代码是所应遵循的规范,有了这种“稳固”的ABI,我们就可以在“class-continuation分类”或实现文件中定义实例变量了。所以说,不一定要在接口中把全部实例变量都声明号,可以将某些变量从接口的public区段里移走,以便保护与类实现有关的内部信息。

这个问题还有一种解决办法,就是尽量不要直接访问实例变量,而应该通过存取方法来做,虽说属性最终还是得通过实例变量来实现,但它却提供了一种简洁的抽象机制,你可以自己编写存取方法,然而在正规的OC编码风格中,存取方法有着严格的规定。正是因为有这种严格的命名规范,OC才能根据名称自动创建出存取方法。这时Property语法就可以派上用场了。

属性特质

原子性

在默认情况下,有编译器所合成的方法会通过锁定机制确保其原子性(atomicity)。如果属性具备nonatomic特质,则不使用同步锁。请注意,尽管没有名为“atomic”的特质(如果某属性不具备nonatomic特质,那它就是原子的(atomic)),但是仍然可以在属性特质中写明这一点。编译器不会报错。若是自己定义存取方法,那么就应该遵从与属性特质相符的原子性。

读/写权限

具备readwrite特质的属性拥有getter和setter方法,若该属性由@synthesize实现,则编译器上会自动生成这两个方法。

具备readonly特质的属性仅拥有getter方法。

你可能感兴趣的:(第六条 “属性”概念)