iOS基础03--category & extension & protocol
Category(分类)
先来一波代码看看 category
@interface Person : NSObject
- (void)printName;
@end
@interface Person (category)
- (void)printName;
+ (id)shareMange;
@end
static Person * _shareInstance;
@implementation Person
- (void)printName{
NSLog(@"print Person");
}
@end
@implementation Person (category)
- (void)printName{
NSLog(@"print Person (category)");
}
+ (id)shareMange{
static dispatch_once_t oneToken;
dispatch_once(&oneToken, ^{
_shareInstance = [[Person alloc]init];
});
return _shareInstance;
}
@end
-
特性1:category 可以增加实例方法和类方法;(虽然无法添加成员变量是因为runtime时objc_class结构体的大小是没法改变的,但是objc_class的方法链表是一个二维指针,虽然也是不能改变大小,但是可以改变内存区域的值,让它达到动态添加方法的目的)
-
特性2:category 添加的方法会覆盖掉原来的方法(实际上不是覆盖掉,而是在运行时从类的结构体的方法列表中查找的时候,category方法添加的列表是在上面的,所以就会先掉用category的方法),优先级是:分类方法-->原来类的方法-->原来类的父类的方法;如果子类的类别或者子类本身也添加了和父类的类别同样的方法,优先级也是差不多,先考虑自身的列表,然后才查父类的方法列表,就是:子类分类方法-->子类实现的方法-->父类分类方法-->父类实现方法;
-
特性3:category添加的方法,子类是可以继承的;
-
特性4:category是在运行时加载的;
-
特性5:category不能添加成员变量(属性);因为category是在runtime的时候加载的,class类型指针在runtime的时候是指向一个objc_class结构体的。而结构体本身大小是固定的。所以编译的时候是没法加成员变量的。但是用runtime是可以给它添加属性的,而这样添加属性和给原来的类本身添加属性性质是一样的。
面试题:category实现的方法是放在哪的?
//
那接下来,就用runtime实现一下给category添加属性
@interface Person (category)
@property (nonatomic,copy)NSString * name;
@end
#import <objc/message.h>
@implementation Person (category)
- (void)setName:(NSString *)name{
objc_setAssociatedObject(self, "name", name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSString *)name{
return objc_getAssociatedObject(self, "name");
}
@end
Extension (扩展)
extension其实就是只有一个.h文件。一般我们是把它放到类的.m文件中使用。一般私有的成员变量、属性、方法可以通过extension在.m文件中声明。然后extension是编译的时候检查的。如果在.m文件中通过extension实现了一些私有方法和属性,那么在外面使用的时候就会马上报告错误。其次extension是必须有一个类的源码才可以添加的。所以一些系统类,比如NSString是没法添加扩展的。
@interface Person ()
@property (nonatomic, copy) NSString * className;
@end
@implementation Person
@end
category是可以被继承的。而extension是不可以被继承的,通常是为了实现私有方法、属性才用到的。
protocol(协议)
protocol就是协议。面试经常问到的多继承问题:OC无法实现多继承,但是可以通过protocol实现。
网友评论