Objective-CiOS 开发tom

协议和 NSProxy 实现多继承

2016-10-21  本文已影响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 方法,也就是说,它只可以开辟一块内存空间,而不能初始化. 那么,我怎么样这个类可以变成任意一个类呢?

主要有这样几步,

我一步步说一遍
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 *proxy = [YFProxy alloc];
    [proxy transformToObject:person];
    [proxy performSelector:@selector(setName:) withObject:@"小明"];
    
    [proxy performSelector:@selector(eat)];
     [proxy transformToObject:student];
    [proxy performSelector:@selector(study)];

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

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

猜你喜欢

热点阅读