ios-NSProxy模拟多继承

在网上也看到了个例子是模拟多继承的,大致的应用场景是这样的,如果我们目前有一个类A,还有一个类B,类A有父类,类B也有父类,然后现在我们要完善的功能就是要集合A中的功能以及B中父类的功能,如果有多继承,我们完全可以直接让A类继承自它原本的父类以及B类的父类就可以了。但是在OC中是没有多继承的,所以无法这么做,如果我们要去修改A的父类或者A的类的话太麻烦了,所以这个时候我们就可以用NSProxy来模拟多继承,比如说我们想要在一个类中即实现买书的功能也能实现买衣服的功能,也就是说那个类是个经销商,综合了各种功能,那么我们可以把卖书的经销商和卖衣服的经销商的功能集合在哪个类中,这样我们就可以在一个类中统一的去购买,而不用自己去一一的购买了,大致就是这么一个意思。直接上代码

卖书经销商

#import <Foundation/Foundation.h>

@protocol ZXBookProviderProtocol

-(void)purchaseBookWithTitle:(NSString *)bookTitle;

@end

@interface ZXBookPrvider : NSObject

@end
类实现

#import "ZXBookPrvider.h"

@implementation ZXBookPrvider

-(void)purchaseBookWithTitle:(NSString *)bookTitle
{
    NSLog(@"bought it %@",bookTitle);
}
@end
卖衣服的经销商

#import <Foundation/Foundation.h>
typedef NS_ENUM(NSInteger,ZXClothesSize)
{
  ZXClothesSizeSmall=0,
  ZXClothesSizeMedium,
  ZXClothesSizeLarge
};
@protocol ZXClothesProviderProtocol

-(void)purchaseClothesWithSize:(ZXClothesSize)size;

@end

@interface ZXClothesProvider : NSObject

@end
类实现

#import "ZXClothesProvider.h"

@implementation ZXClothesProvider
-(void)purchaseClothesWithSize:(ZXClothesSize)size
{
    NSString * string=nil;
    switch (size) {
        case ZXClothesSizeSmall:
            string=@"small size";
            break;
        case ZXClothesSizeMedium:
            string=@"medium size";
            break;
        case ZXClothesSizeLarge:
            string=@"small size";
            break;
        default:
            break;
    }
    NSLog(@"bought some clothes of %@",string);
}
@end
综合经销商

#import <Foundation/Foundation.h>
#import "ZXClothesProvider.h"
#import "ZXBookPrvider.h"
@interface ZXPurchaseProxy : NSProxy<ZXBookProviderProtocol,ZXClothesProviderProtocol>
+(instancetype)gainProxy;
@end
类实现

#import "ZXPurchaseProxy.h"
#import <objc/message.h>
@interface ZXPurchaseProxy()
{
    ZXBookPrvider * _bookProvider;
    ZXClothesProvider * _clothesProvider;
    NSMutableDictionary * _methodsMap;
}
@end

@implementation ZXPurchaseProxy
#pragma mark 类方法
+(instancetype)gainProxy
{
    return [[ZXPurchaseProxy alloc]init];
}
#pragma mark 初始化方法
-(instancetype)init
{
    _methodsMap=[NSMutableDictionary dictionary];
    _bookProvider=[[ZXBookPrvider alloc]init];
    _clothesProvider=[[ZXClothesProvider alloc]init];
    
    //在字典中存储调用者和调用的方法
    [self registerMethodsWithTarget:_bookProvider];
    [self registerMethodsWithTarget:_clothesProvider];
    
    return self;
}
#pragma mark 添加方法
//添加方法进入字典中
-(void)registerMethodsWithTarget:(id)target
{
   unsigned int count=0;
    //获取调用者的方法的列表
    Method * methodList=class_copyMethodList([target class], &count);
    //把方法存储都字典中
    for(int i=0;i<count;i++)
    {
        //获取方法
        Method temp = methodList[i];
        //获取方法编号
        SEL selector = method_getName(temp);
        //获取方法的名字
        const char * name = sel_getName(selector);
        //存储到字典中
        [_methodsMap setObject:target forKey:[NSString stringWithUTF8String:name]];
    }
    free(methodList);
}
#pragma mark NSProxy的方法
//生成方法签名
-(NSMethodSignature *)methodSignatureForSelector:(SEL)sel
{
    //获取方法名
    NSString * name = NSStringFromSelector(sel);
    
    //寻找字典中的target
    id target = _methodsMap[name];
    
    //检查target
    if(target&&[target respondsToSelector:sel])
    {
        return [target methodSignatureForSelector:sel];
    }
    else
    {
        return [super methodSignatureForSelector:sel];
    }
}
//配发消息
-(void)forwardInvocation:(NSInvocation *)invocation
{
    SEL sel = invocation.selector;
    //获取方法的名字
    NSString * name = NSStringFromSelector(sel);
    //查找调用者
    id target = _methodsMap[name];
    //检查调用者
    if(target&&[target respondsToSelector:sel])
    {
        [invocation invokeWithTarget:target];
    }
    else
    {
        [super forwardInvocation:invocation];
    }
}
@end

参考文章: http://ios.jobbole.com/87856/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值