1.3 类属性
我们知道,在实例方法中,self指的是类实例,而在类方法中,self指的是类,而不是类实例,一般情况下也是可以直接将self换成类名来调用。类实例是由类创建的,那类是怎么来的呢?图1-2是类关系图,可以看出,类都是来自于一个叫作MetaClass的类。
图1-2 类的关系
类可以看作是其元类的实例。与此同时,我们再看一下objc对象对应的结构体:
其中有一个methodLists,顾名思义是存储该对象方法的列表,如果了解Objective-C的运行时机制,一个类实例调用方法,会在该类中的方法表中检索,也就是该methodLists,但并不一定能找到,如果不能找到,则会沿着图1-2中的继承链路来逐层向父类查找,也就是在父类中的methodLists查找,如果都找不到,则会按消息传递的逻辑进行。同理,一个类的变量也是存在该类的ivars中,如果没有,则会在父类的ivars中查找。
Xcode 8的发布,表示Swift进入了3.0的时代,同时Objective-C也引入了类属性,用法是在property的修饰符中加入class,代表这是一个类属性。在原来的Person.h中添加:
@property (nonatomic, copy, class) NSString * name;
类属性的出现,不仅是为了与新兴语言Swift在iOS开发中相迎合,更为许多iOS开发中的超频使用者带来福音。在很多类的属性当中,并不需要设置为实例属性,因为每个实例都会创建一遍,开辟一段内存。事实上,对于类属性来说,一个类只要有一个实例就行了。但是在使用类属性时也需要注意,使用方法仍然比较烦琐,有些类似自己实现property的感觉。
调用:
NSLog(@"%@", Person.name);
[Person setName:@"Tom"];
NSLog(@"%@", Person.name);
输出结果:
PersonName Tom
这里需要注意的是,都应该使用“+”表示这是一个类方法,同时声明一个static静态变量来存储,类属性本身不提供存储,有些类似于Swift中的计算属性。类方法的使用,可以更好地在类中声明合适的属性,也能更好地与Swift进行相互转化。
本节小结
(1)类实例对象是由类实例化得到的,而类是由其元类得到的,因此可以看作元类的实例;
(2)了解类属性,可以直接通过类直接访问,但需要手动添加setter、getter方法以及实例变量,Swift中的类属性则可以直接访问。