美文网首页
iOS 多继承实现方式

iOS 多继承实现方式

作者: 搬砖的crystal | 来源:发表于2022-06-28 15:50 被阅读0次

一、单继承与多继承概念

继承是面向对象的基本特征之一,在具体语言的语法上设计有两种形式:多继承与单继承。

1.单继承

一个子类只有一个父类。
优点:类层次机结构清晰,设计上更容易把握。
缺点:在丰富度要求较高和较复杂的情况下,单继承从设计结构上无法满足。

2.多继承

一个子类可以有多个父类。
优点:由于同时具备多个父类的特征,让子类拥有更高的丰富度。
缺点:会让继承的结构变得更复杂,而且会出现菱形继承的风险。

Objective-C 不支持多继承,但我们可以间接的实现(协议、分类、消息转发)

二、实现多继承的几种方式

1.组合

DJTestClassC 继承 DJTestClassA 和 DJTestClassB 的方法,具体实现如下:
DJTestClassA:

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

#import "DJTestClassA.h"

@implementation DJTestClassA
-(void)classAMethod{
    NSLog(@"classAMethod");
}
@end

DJTestClassB:

#import <Foundation/Foundation.h>

@interface DJTestClassB : NSObject
-(void)classBMethod;
@end

#import "DJTestClassB.h"

@implementation DJTestClassB
-(void)classBMethod{
    NSLog(@"classBMethod");
}
@end

DJTestClassC:

#import <Foundation/Foundation.h>

@interface DJTestClassC : NSObject
-(void)classCMethod;
@property (nonatomic,strong)DJTestClassA *classA;
@property (nonatomic,strong)DJTestClassB *classB;
@end

#import "DJTestClassC.h"
#import "DJTestClassA.h"
#import "DJTestClassB.h"

@implementation DJTestClassC
-(instancetype)init{
    if (self = [super init]) {
            self.classA = [[DJTestClassA alloc]init];
            self.classB = [[DJTestClassB alloc]init];
        }
        return self;
}
-(void)classCMethod{
    [self.classA classAMethod];
    [self.classB classBMethod];
}
@end
2.协议

一个类可以遵守多个协议,需要实现多个协议的方法,以此来达到多继承的效果。概念上的多继承和多继承应该是继承父类的属性和方法,并且不需要重写即可使用,通过协议实现多继承有以下不同:

  • 子类需要实现协议方法
  • 由于协议无法定义属性(只是声明 setter/getter 方法),所以该方法只能实现方法的多继承。

DJTestClassC 类继承 DJProtocolA 和 DJProtocolB 协议方法并实现,具体实现如下:
DJProtocolA:

#import <Foundation/Foundation.h>
@protocol DJProtocolA <NSObject>
-(void)protocolMethodA;
@end

DJProtocolB:

#import <Foundation/Foundation.h>
@protocol DJProtocolB <NSObject>
-(void)protocolMethodB;
@end

DJTestClassC:

#import <Foundation/Foundation.h>
#import "DJProtocolA.h"
@interface DJTestClassC : NSObject<DJProtocolA>//DJProtocolA公有方法,外部可调用

@end


#import "DJTestClassC.h"
#import "DJProtocolB.h"
@interface DJTestClassC ()<DJProtocolB>//DJProtocolB私有方法
@end

@implementation DJTestClassC
-(void)protocolMethodA{
    NSLog(@"protocolMethodA");
}
-(void)protocolMethodB{
    NSLog(@"protocolMethodB");
}
@end
3.类别

相对于协议,分类方法有一定的优势:

  • 可以为分类添加方法。
  • 可以为分类添加实例(通过 runtime 的关联属性),这是协议做不到的。
  • 分类方便管理。

用分类实现上述协议实现的功能外再添加一个属性,创建一个 DJTestClassC 的分类,如下:

#import "DJTestClassC.h"

@interface DJTestClassC (extension)
// 声明属性
@property (nonatomic, copy) NSString *string;

@end


#import "DJTestClassC+extension.h"
#import <objc/runtime.h>
@implementation DJTestClassC (extension)
// 为分类添加属性
static const char *KString = "string";

- (NSString *)string {
    return objc_getAssociatedObject(self, KString);
}

- (void)setString:(NSString *)string {
    objc_setAssociatedObject(self, KString, string, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

//分类重写方法会覆盖原类方法
-(void)protocolMethodA{
    NSLog(@"protocolMethodA--extension");
}
-(void)protocolMethodB{
    NSLog(@"protocolMethodB--extension");
}

@end
4.消息转发
(1)快速转发
#import <Foundation/Foundation.h>
@interface DJTestClassC : NSObject
@end


#import "DJTestClassC.h"
#import "DJTestClassA.h"
#import "DJTestClassB.h"
@interface DJTestClassC ()
@end

@implementation DJTestClassC

- (id)forwardingTargetForSelector:(SEL)aSelector {
    DJTestClassA *classA = [[DJTestClassA alloc] init];
    DJTestClassB  *classB  = [[DJTestClassB alloc] init];
    
    if ([classA respondsToSelector:aSelector]) {
        return classA; // 转发给 classA 对象
    }
    else if ([classB respondsToSelector:aSelector]) {
        return classB; // 转发给 classB 对象
    }
    return nil;
}

@end

调用的时候:

    DJTestClassC *c = [[DJTestClassC alloc]init];
    //1.在performSelector中使用NSSelectorFromString会造成警告,可以通过设置不检测performSelector内存泄露关闭警告
    [c performSelector:NSSelectorFromString(@"classAMethod")];
    //2.类型强转
    [(DJTestClassB *)c classBMethod];

通过消息的快速转发,实现了动态性,真正的将方法交给其他类来实现,而非协议或者分类所需要自行实现。同时,消息转发也给我们了充分的灵活性,在不暴露这些接口的情况下通过类型强转来调用。

(2)慢速转发

慢速转发由程序员控制转发的过程,同时也可以实现对多个对象的转发,快速转发只能把该方法直接转发给其他某对象。

#import "DJTestClassC.h"
#import "DJTestClassA.h"
#import "DJTestClassB.h"
@interface DJTestClassC ()
{
    // 创建成员实例
    DJTestClassA *_classA;
    DJTestClassB  *_classB;
}
@end

@implementation DJTestClassC

-(instancetype)init{
    self = [super init];
        if (self) {
            _classA = [[DJTestClassA alloc]init];
            _classB = [[DJTestClassB alloc]init];
        }
    return self;
}


-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    // 尝试自行实现方法签名
    NSMethodSignature *methodSignature = [super methodSignatureForSelector:aSelector];
    if (methodSignature == nil) { // 若无法实现,尝试通过多继承得到的方法实现
        
        // 判断方法是哪个父类的,通过其创建方法签名
        if ([_classA respondsToSelector:aSelector]) {
            methodSignature = [_classA methodSignatureForSelector:aSelector];
        }
        else if ([_classB respondsToSelector:aSelector]) {
            methodSignature = [_classB methodSignatureForSelector:aSelector];
        }
    }
    return methodSignature;
}

// 为方法签名后,转发消息
- (void)forwardInvocation:(NSInvocation *)anInvocation {
    SEL sel = [anInvocation selector];
    // 判断哪个类实现了该方法
    if ([_classA respondsToSelector:sel]) {
        [anInvocation invokeWithTarget:_classA];
    }
    else if ([_classB respondsToSelector:sel]) {
        [anInvocation invokeWithTarget:_classB];
    }
}
@end
5. NSProxy

https://www.jianshu.com/p/0c31fed0a27a

相关文章

  • category与extension

    category与extension 转载iOS实现多继承的几种方式 转载

  • iOS 多继承实现方式

    一、单继承与多继承概念 继承是面向对象的基本特征之一,在具体语言的语法上设计有两种形式:多继承与单继承。 1.单继...

  • iOS实现多继承的几种方式

    背景 我们都知道OC是不支持多继承的,这是因为消息机制名称查找发生在运行时而非编译时,很难解决多个基类可能导致的二...

  • iOS 实现多继承的几种方式

    我们都知道OC是不支持多继承的,这是因为消息机制名称查找发生在运行时而非编译时,很难解决多个基类可能导致的二义性问...

  • iOS 中几种多继承的实现方式

    单继承与多继承概念 继承是面向对象的基本特征之一,在具体语言的语法上设计有两种形式:多继承与单继承。 单继承 一个...

  • Objective-c的类可以多重继承么?

    Object-c的类没有多继承,只支持单继承,如果要实现多继承的话,可以通过类别和协议的方式来实现,OC类似于多继...

  • iOS 不支持多继承,实现多继承的4种方式

    classA 实现了methodA 方法 classB 实现了 methodB 方法 classC 要同时实现m...

  • go 面向对象编程

    尽管GO语言没有封装,继承,多态这些概念,但同样通过别的方式实现这些特性封装:通过方法实现继承:通过匿名字段实现多...

  • ios多重继承的实现

    ios没有直接的多重继承的实现机制,但可以从其他方面来实现类似的效果。 方式一: 采用组合、聚合的方式,比较常见。...

  • iOS面试题

    1.Object-c的类可以多继承吗?可以实现多个接口吗? 答:不可以多继承,可以用实现多个接口的方式来完成多重继...

网友评论

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

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