上一章Objective-C开发教程请查看:Objective-C使用继承
这一节我们讨论OC中的NSObject对象,主要是因为这是OC所有类的超类,所有类都继承它,使其它子类可以使用OC对象的基本功能,另外NSObject对象遵循了NSObject协议。
这不是一个简单的类,在开发中常常都会涉及到,先花点时间了解一下,对于以后的开发有很大帮助,因为很有可能会查一个类,直至回到NSObject,而又不了解,那么会很麻烦。
顺便吐槽,OC的超类相对于Java的Object来说,提供的功能实在太多了。下面我们摘一些重点和常用的功能进行讨论。
NSObject的简单解释
首先我们要明确,NSObject是一个数据类型,更原始一点又叫做抽象数据类型,也就是有它的数据结构,那么就有对应的算法(数据结构和算法中,一个数据结构对应有一系列的算法操作)。既然这样,那么NSObject的主要数据是什么呢?
当然就是类了(class),这个类的结构可以作为数据,和类相关的还有它的父类,类有什么?属性和方法,也作为数据,那么操作方法,不外乎就是与类、属性和方法相关的了。但当然第一步是处理内存方面的问题,涉及到内存的就是这个类的声明周期的描述了。
下面的描述参考苹果的开发文档。
初始化一个类
+initialize类方法,在类调用第一个方法之前,调用该初始化方法,但是如果类一直不使用其它方法,则不会被调用。另外该方法是阻塞的,独立的初始化操作不要再这里进行,子类没有重写该方法,则调用父类的initialize方法。
+ (void)initialize {
if (self == [ClassName self]) {
// ... do the initialization ...
}
}
+(void)load类方法,每当类或类别被添加到Objective-C运行时时调用,实现此方法以在加载时执行类特定的行为。只要文件被引用就会被调用,只调用一次。
创建、复制和释放对象
+alloc,返回接受类的新实例,就是给对象分配一个内存空间,alloc通过调用+allocWithZone实现。
+allocWithZone:,返回接受类新实例,参数被忽略,传入一个nil即可。
-new:分配接收类的新实例,向其发送init消息,并返回已初始化的对象,相当于调用了alloc和init。
-init:初始化新对象的属性成员,基本数据类型初始化为0,OC指针初始化为nil,C指针初始化为NULL。但是有可能出于某些原因初始化失败,因而在重写init方法的时候,首先需要向基类发送init消息[super init],然后判断是否初始成功。
-dealloc:释放对象占用的内存。ARC下不直接发送dealloc消息,相反,对象的dealloc方法由运行时调用。当不使用ARC时,dealloc的实现必须调用超类的实现作为它的最后一条指令,可以管理一些对象的生命周期。
因而新建一个对象有以下几种形式:
Student *student = [Student new];
Student *student2 = [[Student alloc] init];
Student *student3 = [[Student allocWithZone:nil] init];
-copy:返回copyWithZone:返回的对象。
+copyWithZone:实现NSCopying协议,返回接收者,
-mutableCopy:返回mutableCopyWithZone返回的对象,其中zone为nil。
+mutableCopyWithZone:实现NSMutableCopying协议,返回接收者。
这里涉及到深拷贝和浅拷贝的问题,首先无论是哪一种拷贝都是一层拷贝,视乎于是拷贝指针,还是拷贝内容。拷贝主要分为两种情况:
- 对象拷贝:不可变对象copy为浅拷贝,返回不可变;可变对象copy为深拷贝,返回可变。不可变对象和可变对象mutableCopy都是深拷贝,返回可变。
- 容器拷贝:不管是哪种情况,容器内的数据拷贝后都不会变,因为复制的只是容器,不可变copy为浅拷贝,返回不可变;可变对象copy为深拷贝,返回可变。不可变对象和可变对象mutableCopy都是深拷贝,返回可变。
可以这样说,有mutable的情况(不管是调用者还是调用方法)都是深拷贝,其它情况为浅拷贝。
标识类
+class:返回类对象。
+superclass:返回接收者超类的类对象。
+isSubclassOfClass:返回一个布尔值,该值指示接收类是给定类的子类,还是与给定类相同。
+comformsToProtocol:返回一个布尔值,该值指示接收方是否遵循给定的协议。
+description:返回表示接收类内容的字符串。
IMP和SEL
SEL和IMP都是类型,其中:
- SEL:是类成员方法的指针,不同于C函数指针,SEL相当于方法的编号key,不可以按照函数方式调用。
- IMP:函数指针,是实际的函数,可以直接按函数方式调用。
- SEL和IMP:通过HashTable: key-value一一对应,类似散列表,这样的好处是,向接受者发送消息时,可以快速找到对应的消息并执行,因为散列表的时间复杂度为O(1)。
获取SEL:@selector()取类方法编号、NSSelectorFromString(方法签名)取方法签名的字符串形式。
获取IMP:-methodForSelector、+instaceMethodForSelector。
测试类中是否有指定的SEL:instancesRespondToSelector。
调用方法:
- 1、IMP f => f();直接按照函数调用的方式调用。
- 2、SEL sel => performSelector:sel,使用类似performSelector的方法进行调用,NSObject中有很多不同的类似的方法。带参数在withObject指定,多个参数可以使用多个withObject。
另外还有一个hash和isEqual函数,hash是哈希值,OC使用哈希值来比较两个对象是否相等。
本节暂时先介绍以上内容,其中有一部分内容留到OC运行时的时候进行讨论。
评论前必须登录!
注册