美文网首页Objective-CiOS 开发tom
协议和 NSProxy 实现多继承

协议和 NSProxy 实现多继承

作者: 小冰山口 | 来源:发表于2016-10-21 01:04 被阅读416次

OC 中一个类只有一个父类, 这就是单一继承, 但是我们可以用协议NSProxy 实现多继承

先说协议, 协议我们用的最多的地方,就是代理,其实代理不叫代理,叫委托, 这里就不多说了,相信大家都很熟了
那么 protocol 这个东西,是可以遵守多个的,遵守了之后,实现 protocol 中的方法,就OK 了,就是这么简单,轻松, easy

比如我有两个协议, 分别是 YFPerson,YFChild

#import <Foundation/Foundation.h>

@protocol YFPerson <NSObject>
@required
@property (nonatomic,copy,readonly)NSString *name;
- (NSInteger) age;
- (void)eat;
- (void)sleep;
@optional
- (void)play;
- (void)setName:(NSString *)newName;
@end
#import <Foundation/Foundation.h>

@protocol YFChild <NSObject>
@required
- (NSString *)nickname;
- (void)introduceMyselfWithName:(NSString *)name nickname:(NSString *)nickname age:(NSInteger)age;
@optional
- (void)study;
@end

那么, 我在新创建的一个 YFStudent 类中, 只要遵守上面两个协议, 实现协议里的方法, 就可以在一个类中,实现多个协议中的方法了.

YFStudent.m


- (NSString *)nickname
{
    return @"龙儿";
}

- (NSInteger)age
{
    return 19;
}

- (void)sleep{
    NSLog(@"sleep");
}

- (void)eat{
    NSLog(@"eat");
}

- (void)introduceMyselfWithName:(NSString *)name nickname:(NSString *)nickname age:(NSInteger)age
{
    NSLog(@"我叫%@,小名%@,今天%@岁了", name,nickname,@(age));
}

这样, 我在控制器的 viewDidLoad 方法中,创建 YFStudent 对象, 然后就可以调协议中的任何方法了

- (void)viewDidLoad {
    [super viewDidLoad];
    
    YFStudent *student = [[YFStudent alloc]init];
    student.name = @"小龙女";
    [student eat];
    [student sleep];
    [student introduceMyselfWithName:student.name nickname:student.nickname age:student.age];
}

运行后,正确输出

运行结果
现在再说 NSProxy, 这才是真的代理,不信去翻词典

这个类是和 NSObject 平起平坐的, 而且这个类没有 init 方法,也就是说,它只可以开辟一块内存空间,而不能初始化. 那么,我怎么样这个类可以变成任意一个类呢?

主要有这样几步,

  • 我先设置一个类 YFProxy, 继承自 NSProxy
  • 为 YFProxy 设置一个 NSObject 属性
  • 自定义一个转换方法,相当于给 NSObject 属性赋值
  • 然后通过这个属性获得调用方法的方法签名
  • 为调用设置目标
  • 调用

我一步步说一遍
1.为外界暴露一个变身方法:

#import <Foundation/Foundation.h>

@interface YFProxy : NSProxy

- (id)transformToObject:(NSObject *)object;

@end

2.设置一个 NSObject 属性

#import "YFProxy.h"

@interface YFProxy ()

@property (nonatomic,strong)NSObject *object;

@end

3.实现变身方法

- (id)transformToObject:(NSObject *)object
{
    self.object = object;
    return self.object;
}

4.重写- (NSMethodSignature *)methodSignatureForSelector:(SEL)see方法获得方法签名

- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel
{
    NSMethodSignature *methodSignature;
    
    if (self.object) {
       methodSignature = [self.object methodSignatureForSelector:sel];
        
    }else{
        
       methodSignature = [super methodSignatureForSelector:sel];
    }
    return methodSignature;
}

5.重写- (void)forwardInvocation:(NSInvocation *)invocation方法改变调用对象,也就是说,让消息实际上发给真正的实现这个方法的类

- (void)forwardInvocation:(NSInvocation *)invocation
{
    if (self.object) {
        [invocation setTarget:self.object];
        
        [invocation invoke];
    }
}
准备就绪,现在要开始变身了

假设我现在有两个类,

YFPerson

#import "YFPerson.h"

@interface YFPerson ()

@property (nonatomic,copy)NSString *name;

@end

@implementation YFPerson

- (void)eat
{
    NSLog(@"%@正在吃饭",self.name);
}

@end

YFStudent

#import "YFStudent.h"

@interface YFStudent ()

@property (nonatomic,copy)NSString *studentNum;

@end

@implementation YFStudent

- (void)study
{
    NSLog(@"哥正在学习");
}

@end

那么我怎么用 YFProxy"继承"这连个类呢?

  • 先初始化两个纯洁的对象
    YFPerson *person = [[YFPerson alloc]init];
    YFStudent *student = [[YFStudent alloc]init];
  • 为 YFProxy 开辟一块内存空间
    YFProxy *proxy = [YFProxy alloc];
  • 变身
    [proxy transformToObject:person];
  • 这样就可以自由自在地调用 Person 类的方法了,person 类的方法甚至是真私有的,都可以调得到,虽然报警告了
    [proxy performSelector:@selector(setName:) withObject:@"小明"];
    
    [proxy performSelector:@selector(eat)];
  • 再变
     [proxy transformToObject:student];
  • 这样又可以调 Student类的方法了
    [proxy performSelector:@selector(study)];

是不是很神奇,当然,这只是初步的探讨,还有很多基于 OC 运行时的东西值得我们去挖掘

上面就是两种实现 OC 多继承的两种方法, 特别是第二种,我可以将 NSProxy 变成任意类,实现任意类的方法,并可以使用其属性.

相关文章

  • 协议和 NSProxy 实现多继承

    OC 中一个类只有一个父类, 这就是单一继承, 但是我们可以用协议和 NSProxy 实现多继承 先说协议, 协议...

  • iOS:NSProxy

    OC 中一个类只有一个父类,这就是单一继承,但是我们可以用协议和NSProxy实现多继承。 1、 protocol...

  • OC中如何实现”多继承“,(NSProxy,Protocol)

    OC 中一个类只有一个父类 但是我们可以用协议和 NSProxy 实现多继承 1. protocol 先说协议 比...

  • NSProxy 实现“多继承”

    之前有在YYWeakProxy看到过 NSProxy 使用,可以解决NSTimer 对 target 是强引用的问...

  • NSProxy实现伪多继承

    Objective-C是不支持多继承的,但是基于消息转发机制我们可以使用NSProxy来实现伪多继承。 1.关于N...

  • iOS NSProxy使用

    简介:通过NSProxy 可以实现类的"伪多继承",demo中KLProxy通过拦截方法修改了cat和dog本来的...

  • NSProxy 使用总结

    NSProxy是一个虚类。它有什么用处呢?OC中类是不支持多继承的,要想实现多继承一般是有protocol的方式,...

  • 记录NSObject 的关系

    NSObject的关系 NSProxy 没有继承NSObject,只实现了NSObject的协议,所以NSProx...

  • 关于 iOS 实现多继承的补充

    刚刚看到一篇文章介绍的是关于iOS多继承的实现,作者也是用NSProxy实现,但是和我之前的有些不一样,在这里做个...

  • Swift 基础(0) - 协议、枚举 、异常

    面向协议 面向对象的问题: 不能实现多继承,且会导致继承关系变得复杂 面向协议的事例: 实现统一加载 nib的 协...

网友评论

本文标题:协议和 NSProxy 实现多继承

本文链接:https://www.haomeiwen.com/subject/gfqfuttx.html