美文网首页
Runtime(四)模拟多继承的实现

Runtime(四)模拟多继承的实现

作者: 炒河粉儿 | 来源:发表于2019-08-16 10:37 被阅读0次

思想

iOS中是不允许多继承的,一个类既可以同时实现其他两个类的方法。一般有两种方式,一种是将这两个类的对象作为参数传入去调用各自的方法,另一种是通过代理协议的方式实现。但追其根本还是通过这两个类进行的方法调用。
我们可以利用runtime,模拟实现多继承的效果,通过消息转发机制中的第三步,方法签名和消息转发可以实现当前类调用方法,转发到对应的实现的类中去实现。

代码

定义两个类,各自声明实现各自的方法。通过协议的方式去声明方法。

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@protocol FruitsProviderProtocol

- (void)buyFruits:(NSString *)fruits;

@end

@interface FruitsProvider : NSObject


@end

NS_ASSUME_NONNULL_END

#import "FruitsProvider.h"

@interface FruitsProvider() <FruitsProviderProtocol>

@end

@implementation FruitsProvider

- (void)buyFruits:(NSString *)fruits
{
    NSLog(@"fruits: %@",fruits);
}

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@protocol RestaurantProviderProtocol

- (void)order:(NSString *)orderName;

@end

@interface RestaurantProvider : NSObject

@end

NS_ASSUME_NONNULL_END

#import "RestaurantProvider.h"

@interface RestaurantProvider() <RestaurantProviderProtocol>

@end

@implementation RestaurantProvider

- (void)order:(NSString *)orderName
{
    NSLog(@"order: %@",orderName);
}

@end

定义一个类,通过遵守协议的方式,将另外两个类的方法引入。

#import <Foundation/Foundation.h>
#import "FruitsProvider.h"
#import "RestaurantProvider.h"

NS_ASSUME_NONNULL_BEGIN

// NSProxy
//抽象的类,虚类,NSProxy没有构造方法,自己去提供构造方法,并且复写方法签名和消息转发两个方法。
@interface TakeOutProxy : NSProxy <FruitsProviderProtocol,RestaurantProviderProtocol>

- (instancetype)init;

@end

NS_ASSUME_NONNULL_END

自定义构造方法,重写init方法,先将两外两个类的方法列表获取到,保存在一个字典中。当外部通过这个类调用方法的时候,由于该类中没有实现这个方法,因此会走消息转发的流程,对当前调用的方法重新签名,通过方法名找到对应实现这个方法的类,将这个消息转发给这个类的对象。从而实现方法的调用。

#import "TakeOutProxy.h"
#import <objc/runtime.h>

@interface TakeOutProxy()

{
    NSMutableDictionary *_methodDict;
}

@end

@implementation TakeOutProxy

//多继承 继承两个类的方法和实现
//解决方法1:通过把这两个类的对象传进来,通过这两个类分别调用两个方法实现。
//解决方法2:通过协议的方式实现。
//这两个方法本质上都是原来的类去实现的这个方法。
//复写方法签名和消息转发两个方法

//通过协议的方式

+ (instancetype)takeOutProxy
{
    return [[TakeOutProxy alloc]init];
}


- (instancetype)init
{
    _methodDict = [NSMutableDictionary dictionary];
    
    [self registerMethodTarget:[FruitsProvider new]];
    
    [self registerMethodTarget:[RestaurantProvider new]];
    
    return self;
}

//将两个类的方法遍历,存放在一个字典中
- (void)registerMethodTarget:(id)target {
    
    unsigned int count = 0;
    
    //runtime 获取方法列表
    Method *method_list = class_copyMethodList([target class], &count);
    
    for (int i = 0; i<count; i++) {
        Method *method = method_list[i];
        SEL *sel = method_getName(method);
        [_methodDict setObject:target forKey:NSStringFromSelector(sel)];
    }
    
    
    //记得释放
    free(method_list);
    
}

- (nullable NSMethodSignature *)methodSignatureForSelector:(SEL)sel
{
    NSString *methodName = NSStringFromSelector(sel);
    
    id target = _methodDict[methodName];
    
    if (target && [target respondsToSelector:sel]) {
        return [target methodSignatureForSelector:sel];
    }else {
        return [super methodSignatureForSelector:sel];
    }
    
}

- (void)forwardInvocation:(NSInvocation *)invocation
{
    SEL sel = [invocation selector];
    NSString *methodName = NSStringFromSelector(sel);
    id target = _methodDict[methodName];
    if (target && [target respondsToSelector:sel]) {
        [invocation invokeWithTarget:target];
    }else {
        [super forwardInvocation:invocation];
    }
}


@end

相关文章

  • Runtime(四)模拟多继承的实现

    思想 iOS中是不允许多继承的,一个类既可以同时实现其他两个类的方法。一般有两种方式,一种是将这两个类的对象作为参...

  • iOS runtime 之跳转页面以及动态添加属性

    序言 runtime 的主要用处有以下几点: 给分类添加属性 消息转发机制 动态交换方法的实现 手动实现多继承(o...

  • oc不用多继承的思考

    runtime使用isa继承链发送消息,多继承的话isa就成了多维数组了。结合c++的多继承原理对比

  • Runtime积累

    一、Runtime 可以做的是事情1、实现多继承2、交换两个方法的实现3、关联对象4、动态创建方法和类5、将 Js...

  • iOS Category

    分类优点 声明私有方法 分解体积庞大的类文件 把Framework私有方法公开 模拟多继承(另外可以模拟多继承的还...

  • 学习JavaScript设计模式——面向对象(四)

    面向对象(四) 继承 4. 多继承——老师不止一位 首先,JavaScript实现多继承是有一些局限性的,因为Ja...

  • 三、Mixin扩展类 多继承

    1. 多继承 首先要清楚: __mro__ 即 继承顺序 1.1 单继承实现: 1.2 多继承实现: 程序 从 ...

  • iOS vc的分离~继承与组合

    一:继承毁一生~~,能用组合就别用继承~~~~谨记!!!当组合无法实现重写父类方法的时候,使用runtime把方法...

  • 07 Java的继承与多态

    继承 Java继承的实现(只支持单继承,而不是多继承,称为接口的多实现)多个类中存在相同属性和行为时,将这些内容抽...

  • day18 单/多继承的实现

    定义人类 定义学生类: 定义工人类 单继承的实现 多继承的实现 定义父亲类 定义母亲类 定义孩子类 多继承的实现

网友评论

      本文标题:Runtime(四)模拟多继承的实现

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