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