美文网首页技术栈
iOS 实现多继承的几种方式

iOS 实现多继承的几种方式

作者: 学不来的凡人 | 来源:发表于2021-03-21 07:25 被阅读0次

    我们都知道OC是不支持多继承的,这是因为消息机制名称查找发生在运行时而非编译时,很难解决多个基类可能导致的二义性问题,那么如果我们想要一个类a同时继承类b和类c,我们要如何做才能达到我们想要的结果呢?我们创建三个类ClassA、ClassB、ClassC,A和B分别有两个方法run和walk,假设我们需要让C同时拥有run和walk方法,我们可以通过下面几种方法来达到我们想要的效果。

    1、组合

    Son添加两个属性father1(- (void)playFootBall),father2(- (void)playBasketball)。那么Son就有了father1和father2的能力。类似于继承了他们两个!!!

    @class Father1,Father2;
    @interface Father1 : NSObject
    - (void)playFootBall;
    @end
    
    @interface Father2 : NSObject
    - (void)playBasketball;
    @end
    
    @interface Son : NSObject
    @property (nonatomic,strong)Father1 *father1;
    @property (nonatomic,strong)Father2 *father2;
    - (void)playBall;
    
    @end
    
    #import "Son.h"
    @implementation Father1
    - (void)playFootBall{
        NSLog(@"playFootBall");
    }
    @end
    @implementation Father2
    - (void)playBasketball{
        NSLog(@"playBasketball");
    }
    @end
    
    @implementation Son
    - (instancetype)init{
        if (self = [super init]) {
            self.father1 = [Father1 new];
            self.father2 = [Father2 new];
        }
        return self;
    }
    - (void)playBall{
        [self.father1 playFootBall];
        [self.father2 playBasketball];
        
    }
    @end
    

    2、delegate和protocol

    将C类需要继承的方法以及属性在A和B中各自声明一份协议,C类遵守这两份协议,同时在C类中实现协议中的方法以及属性

    @protocol ADelegate
    @property (nonatomic,copy)NSString *jinqiu;
    - (void)playFootBall;
    @end
    
    @protocol BDelegate
    @property (nonatomic,copy)NSString *defen;
    - (void)playBasketball;
    @end
    
    @interface C : NSObject
    - (void)playBall;
    @end
    
    #import "C.h"
    @interface C()<ADelegate,BDelegate>
    
    @end
    @implementation C
    - (void)playBall{
        [self playFootBall];
        [self playBasketball];
    }
    - (void)playFootBall{
        self.jinqiu = @"3个进球";
        NSLog(self.jinqiu);
        
    }
    - (void)playBasketball{
        self.defen = @"得了30分";
        NSLog(self.defen);
    
    }
    
    @synthesize jinqiu;
    
    @synthesize defen;
    
    @end
    

    3、消息转发(1、快速转发和2、标准转发)

    @class Dog;
    @interface Dog : NSObject
    - (void)eatShi;
    @end
    @interface Cat : NSObject
    
    - (void)eatFish;
    
    @end
    
    #import "Cat.h"
    @implementation Dog
    - (void)eatShi{
        NSLog(@"吃屎");
    }
    @end
    @implementation Cat
    - (void)eatFish{
        NSLog(@"吃鱼");
    }
    //1、快速转发(有快速转发走快速转发)
    - (id)forwardingTargetForSelector:(SEL)aSelector{
        Dog *dog = [Dog new];
        return dog;
    }
    //2、(没有快速转发走标准消息转发)
    - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{
       Dog *dog = [Dog new];
        
       NSMethodSignature *signature = [dog methodSignatureForSelector:aSelector];
       return  signature;
    }
    - (void)forwardInvocation:(NSInvocation *)anInvocation{
       SEL selector = [anInvocation selector];
        Dog *dog = [Dog new];
       if([dog respondsToSelector:selector]){
           [anInvocation invokeWithTarget:dog];
       }
    }
    @end
    
        [((Dog*)[Cat new]) eatShi];
    2021-03-19 16:37:14.053339+0800 IOS--多继承[79529:1773692] 吃屎
    

    4、类别(category)

    类别也可以用来模拟多继承,比如给当前类添加方法,利用runTime来添加属性,方法不表,别人文章Category与Extension有实现,可以参考

    5、NSProxy

    NSProxy 并没有继承NSObject ,而是实现了NSObject协议
    NSProxy 和 NSObject 类都实现了NSObject 协议 ,我们仔细看发现NSProxy并没有init或new方法 ;这个就尴尬了,这个类是一个魏忠贤版的类。。。。。init方法貌似需要子类去实现,也就是这个类注定要被别的类继承。
    实现与3、消息转发(1、快速转发和2、标准转发)一样,只不过3、消息转发是继承NSObject ,而现在是使用NSProxy和NSObject有共同的协议,创建NSProxy的子类进行消息转发
    结论: 如此看来NSProxy确实更适合实现做为消息转发的代理类, 因为作为一个抽象类, NSProxy自身能够处理的方法极小(仅<NSObject>接口中定义的部分方法), 所以其它方法都能够按照设计的预期被转发到被代理的对象中.而NSObject很多方法自己有实现,例如respondsToSelector:和isKindOfClass,这样的话就不会走消息转发流程。(消息转发是只有当接收者无法处理时才会通过forwardInvocation:来寻求能够处理的对象.)
    总结:NSProxy比NSObject更干净。
    注意:NSProxy这个基类没有定义默认的init方法.

    NSProxy类


    image.png

    相关文章

      网友评论

        本文标题:iOS 实现多继承的几种方式

        本文链接:https://www.haomeiwen.com/subject/zvavcltx.html