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


 在说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的多继承  。。。。。。  





 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值