OC 中一个类只有一个父类, 这就是单一继承, 但是我们可以用协议和 NSProxy 实现多继承
先说协议, 协议我们用的最多的地方,就是代理,其实代理不叫代理,叫委托, 这里就不多说了,相信大家都很熟了
那么 protocol
这个东西,是可以遵守多个的,遵守了之后,实现 protocol
中的方法,就OK 了,就是这么简单,轻松, easy
比如我有两个协议, 分别是 YFPerson,YFChild
1 |
|
1 |
|
那么, 我在新创建的一个 YFStudent
类中, 只要遵守上面两个协议, 实现协议里的方法, 就可以在一个类中,实现多个协议中的方法了.
YFStudent.m
1 | - (NSString *)nickname |
这样, 我在控制器的 viewDidLoad 方法中,创建 YFStudent 对象, 然后就可以调协议中的任何方法了
1 | - (void)viewDidLoad { |
现在再说 NSProxy
, 这才是真的代理,不信去翻词典
这个类是和 NSObject
平起平坐的, 而且这个类没有 init
方法,也就是说,它只可以开辟一块内存空间,而不能初始化. 那么,我怎么样这个类可以变成任意一个类呢?
- 主要有这样几步,
- 我先设置一个类
YFProxy
, 继承自NSProxy
- 为
YFProxy
设置一个NSObject
属性 - 自定义一个转换方法,相当于给
NSObject
属性赋值 - 然后通过这个属性获得调用方法的方法签名
- 为调用设置目标
- 调用
我一步步说一遍
为外界暴露一个变身方法:
1
2
3
4
5
6
7
@interface YFProxy : NSProxy
- (id)transformToObject:(NSObject *)object;
@end设置一个
NSObject
属性1
2
3
4
5
6
7
@interface YFProxy ()
@property (nonatomic,strong)NSObject *object;
@end实现变身方法
1
2
3
4
5- (id)transformToObject:(NSObject *)object
{
self.object = object;
return self.object;
}重写
- (NSMethodSignature *)methodSignatureForSelector:(SEL)see
方法获得方法签名1
2
3
4
5
6
7
8
9
10
11
12
13- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel
{
NSMethodSignature *methodSignature;
if (self.object) {
methodSignature = [self.object methodSignatureForSelector:sel];
}else{
methodSignature = [super methodSignatureForSelector:sel];
}
return methodSignature;
}重写
- (void)forwardInvocation:(NSInvocation *)invocation
方法改变调用对象,也就是说,让消息实际上发给真正的实现这个方法的类1
2
3
4
5
6
7
8- (void)forwardInvocation:(NSInvocation *)invocation
{
if (self.object) {
[invocation setTarget:self.object];
[invocation invoke];
}
}
准备就绪,现在要开始变身了
假设我现在有两个类,
YFPerson
1 |
|
YFStudent
1 |
|
那么我怎么用 YFProxy
“继承”这连个类呢?
先初始化两个纯洁的对象
1
2YFPerson *person = [[YFPerson alloc]init];
YFStudent *student = [[YFStudent alloc]init];为 YFProxy 开辟一块内存空间
1
YFProxy *proxy = [YFProxy alloc];
变身
1
[proxy transformToObject:person];
这样就可以自由自在地调用 Person 类的方法了,person 类的方法甚至是真私有的,都可以调得到,虽然报警告了
1
2
3[proxy performSelector:@selector(setName:) withObject:@"小明"];
[proxy performSelector:@selector(eat)];再变
1
[proxy transformToObject:student];
这样又可以调 Student类的方法了
1
[proxy performSelector:@selector(study)];
是不是很神奇,当然,这只是初步的探讨,还有很多基于 OC 运行时的东西值得我们去挖掘
上面就是两种实现 OC 多继承的两种方法, 特别是第二种,我可以将 NSProxy 变成任意类,实现任意类的方法,并可以使用其属性.