前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Runtime应用(四):NSProxy

Runtime应用(四):NSProxy

作者头像
Helloted
发布2022-06-07 13:53:18
3290
发布2022-06-07 13:53:18
举报
文章被收录于专栏:Helloted
1、继承

继承是面向对象的三个基本特征(封装,继承,多态)之一,Objective-C语法中,是单继承。而多继承可以看作是单继承的扩展。所谓多继承是指派生类具有多个基类,派生类与每个基类之间的关系仍可看作是一个单继承。我们可以利用NSProxy的特性来模拟多继承

NSProxy is an abstract superclass defining an API for objects that act as stand-ins for other objects or for objects that don’t exist yet. Typically, a message to a proxy is forwarded to the real object or causes the proxy to load (or transform itself into) the real object. Subclasses of NSProxy can be used to implement transparent distributed messaging (for example, NSDistantObject) or for lazy instantiation of objects that are expensive to create.

NSProxy是与NSObject并列的一个类,

img
img

它有两个运行时方法

代码语言:javascript
复制
- (void)forwardInvocation:(NSInvocation *)anInvocation;
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel;

我们可以通过消息转发的特性,将消息转发到另外的实例来实现多继承。

2、多继承

先新建两个普通类Teacher和Worker;

代码语言:javascript
复制
#import "Teacher.h"

@implementation Teacher

- (void)teachStudent{
    NSLog(@"我可以教导学生");
}

@end
代码语言:javascript
复制
#import "Worker.h"

@implementation Worker

- (void)workHard{
    NSLog(@"我可以做工");
}

@end

再新建一个类SuperPerson继承自NSProxy

代码语言:javascript
复制
@interface SuperPerson : NSProxy

+ (instancetype)person;

@end

NSProxy与NSObject不同的是,初始化一个NSProxy只需要alloc方法,不需要init方法,为了模仿普通类,我们自定义一个init方法,并在其中做一些初始化

代码语言:javascript
复制
- (instancetype)init{
    _methodsMap = [NSMutableDictionary dictionary];
    Teacher *teacher = [[Teacher alloc] init];
    Worker *worker = [[Worker alloc] init];
    
    // 将"父类"方法继承
    [self inheriteMethodsFromSuperTarget:teacher];
    [self inheriteMethodsFromSuperTarget:worker];
    return self;
}

初始化的主要工作就是将需要继承的类的方法存储好

代码语言:javascript
复制
- (void)inheriteMethodsFromSuperTarget:(id)target{
    unsigned int numberOfMethods = 0;
    Method *method_list = class_copyMethodList([target class], &numberOfMethods);
    for (int i = 0; i < numberOfMethods; i ++) {
        Method temp_method = method_list[i];
        SEL temp_sel = method_getName(temp_method);
        const char *temp_method_name = sel_getName(temp_sel);
        [_methodsMap setObject:target forKey:[NSString stringWithUTF8String:temp_method_name]];
    }
    free(method_list);
}

然后重写两个消息转发的方法

代码语言:javascript
复制
- (void)forwardInvocation:(NSInvocation *)invocation{
    SEL sel = invocation.selector;
    NSString *methodName = NSStringFromSelector(sel);
    
    //查找对应的target
    id target = _methodsMap[methodName];
    
    if (target && [target respondsToSelector:sel]) {
        [invocation invokeWithTarget:target];
    } else {
        [super forwardInvocation:invocation];
    }
}

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

可以看到虽然,没有实现workHard和teachStudent两个方法,我们依旧可以调用者两个其他类的方法,模拟成了多继承。

完整代码,可以在github下载

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、继承
  • 2、多继承
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档