NSProxy浅谈--- Objective-c 伪多继承

来源:互联网 发布:树莓派开源人工智能 编辑:程序博客网 时间:2024/06/05 03:57


 在说NSProxy之前,我们来说一个类NSObject ;如果你学的第一门计算机语言是Java的话,那么你可能想当然的认为在OC中NSObject是所有类的父类,那么今天你需要改变你一贯的认识了;在OC中NSProxy是少数不继承NSObject类的类,神马? 有没有搞错!!!! 


眼见为实 ,  我们发现NSProxy 并没有继承NSObject ,而是实现了NSObject协议 ,其实我们的NSObject类也实现了这个NSObject协议,来张图



NSProxy 和 NSObject 类都实现了NSObject 协议 ,我们仔细看发现NSProxy并没有init或new方法 ;这个就尴尬了,这个类是一个魏忠贤版的类。。。。。init方法貌似需要子类去实现,也就是这个类注定要被别的类继承。

我们今天的主题是伪多继承,神马是伪多继承了 ? 有些语言是支持多继承的,比如C++ 和Python ,也就是一个类有多个父类; 但是 我们又知道Java 和 OC是不支持多继承的  ,但是Java支持多接口实现,OC也支持多代理实现 



实现多个代理这个我们经常使用,但是说到OC的类多继承,这个咋搞了 ????

我们来借助 NSProxy 这个类 ,来搞一个伪多继承 ,注意伪多继承 !!!!!!!

首先 我们新建两个车类 ,一个是BMW ,另外一个是一代神车五菱宏光

首先是BMW

#import <Foundation/Foundation.h>@interface BMWCar : NSObject-(void)fastFunction;@end

BMW跑得快,但是价格较高

#import "BMWCar.h"@implementation BMWCar-(void)fastFunction{    NSLog(@"BMW 速度很快");}@end

第二个是一代神车五菱宏光  

#import <Foundation/Foundation.h>@interface WulingCar : NSObject-(void)cheapFunction;@end

五菱宏光便宜

#import "WulingCar.h"@implementation WulingCar-(void)cheapFunction{    NSLog(@"一代神车 很便宜");}@end

那么 , 我要搞一个车 ,既满足五菱宏光的便宜又满足BMW的速度快, 该如何是好了 ? 也就是我需要一个类,这个类既能使用五菱宏光的cheapFunction方法 也能使用BMW的 fastFunction该如何搞一搞了  ??? 说到这里,我简单的把OC中方法调用说下, 这属于runtime内容 ,水深的很 。。。。。。 


其实方法调用我可以理解为 :对象向系统发送一条消息,这个很重要,既然消息能被发送,那么是不是有办法将它拦截下来然后转发了 ?? 我们来搞一搞我们自己 的 NSProxy 这个类 

#import <Foundation/Foundation.h>@class BMWCar;@class WulingCar;@interface BaseProxy : NSProxy-(id)initWithCar1:(BMWCar *)car1 andCar2:(WulingCar *)car2;@end

这个类将五菱宏光和BMW关联起来 ,然后我们来看下NSProxy这个类 ,有两个方法很关键



- (void)forwardInvocation:(NSInvocation *)invocation;- (nullable NSMethodSignature *)methodSignatureForSelector:(SEL)sel

可以这里理解:一个是消息转发 ;一个是获取消息签名

然后我直接上代码 

#import "BaseProxy.h"#import "BMWCar.h"#import "WulingCar.h"@interface BaseProxy ()@property (strong,nonatomic) BMWCar *bmwCar;@property (strong,nonatomic) NSMutableArray *arrList;@property (strong,nonatomic) WulingCar *wulingCar;@end@implementation BaseProxy-(id)initWithCar1:(BMWCar *)car1 andCar2:(WulingCar *)car2{    self.arrList = [[NSMutableArray alloc] init];    self.bmwCar = car1;    self.wulingCar = car2;        return  self;}- (void)forwardInvocation:(NSInvocation *)invocation{        SEL sel =  [invocation selector];        id bmw = [self.bmwCar methodSignatureForSelector:sel];    if (bmw) {         NSLog(@" invocation invokeWithTarget:   宝马  ");        [invocation invokeWithTarget:self.bmwCar];    }    id wl = [self.wulingCar methodSignatureForSelector:sel];    if (wl) {        NSLog(@" invocation invokeWithTarget:   五菱宏光  ");        [invocation invokeWithTarget:self.wulingCar];    }        id lt = [self.arrList methodSignatureForSelector:sel];    if (lt) {        NSLog(@" invocation invokeWithTarget:   NSMutableArray  ");        [invocation invokeWithTarget:self.arrList];    }    }- (nullable NSMethodSignature *)methodSignatureForSelector:(SEL)sel{        id bmw =  [self.bmwCar methodSignatureForSelector:sel];    if (bmw) {                NSLog(@" methodSignatureForSelector:   宝马  ");        return bmw;    }        id wl =  [self.wulingCar methodSignatureForSelector:sel];    if (wl) {        NSLog(@" methodSignatureForSelector:   五菱宏光  ");        return wl;    }            id lt =  [self.arrList methodSignatureForSelector:sel];    if (lt) {        NSLog(@" methodSignatureForSelector:   NSMutableArray  ");        return lt;    }        return [super methodSignatureForSelector:sel];}-(BOOL)respondsToSelector:(SEL)aSelector{        NSLog(@" respondsToSelector:   aSelector  ");    if ([self.bmwCar respondsToSelector:aSelector]) {                NSLog(@" respondsToSelector:   宝马  ");        return YES;    }    if ([self.wulingCar respondsToSelector:aSelector]) {                NSLog(@" respondsToSelector:   五菱宏光  ");        return YES;    }        if ([self.arrList respondsToSelector:aSelector]) {                NSLog(@" respondsToSelector:   NSMutableArray  ");        return YES;    }        return NO;}@end


然后如何调用BMW 和五菱宏光的方法了 ???  

第一步 , 我们需要 把实例创建出来 

    id bs = [[BaseProxy alloc] initWithCar1:[BMWCar new] andCar2:[WulingCar new]];    BaseProxy *proxy = [[BaseProxy alloc] initWithCar1:[BMWCar new] andCar2:[WulingCar new]];

上面有两个实例 ,  一个是id 类型的(id类型不是NSObject类型,而是一个万能的指针) ,一个是 BaseProxy类型的 

然后分别看下 ,是否相应 BMW 和 五菱宏光的方法 


都响应 !!!!! 但是 



上图说明了一切 , 所以 这里我们使用id 类型  

然后 我们调用下 BMW的 fastFunction方法  



再执行 五菱宏光的方法



我们发现,我们在调用方法的时候先执行的是 methSignature方法,在执行 invocation ;我们可以这么理解 ,所谓的NSProxy伪多继承的本质是 :先通过对象和方法获取方法签名, 然后对象验证签名不为空 对象将消息转发, 这话理解起来有点抽象 。。。 来张图 




那么 所谓的多继承其实就是一个消息转发的动作  ,但是NSProxy确完成了多继承的一些功能 ,如何两个类里面的方法是一样的该如何解决了 ????  这里不讨论 。。。  

上面的BaseProxy 不仅仅 有 BMWCar 的fastFunction方法 ,而且可以使用WulingCar 中的cheapFunction方法  ,然后更绝的是 ,它居然还能 使用NSMutableArray方法 



以上就是所谓NSProxy的多继承  。。。。。。  





 


原创粉丝点击