iOS:继承详解

Apple

目录
一,基本概念
二,优缺点
三,高耦合的示例
四,使用要点
五,使用场景
六,Super简单介绍
七,替代方案
八,多继承html

一,基本概念

继承、封装、多态是面向对象的三大支柱。OC只支持单继承,父类能够有多个子类,但子类有且仅有一个父类git

二,优缺点

优势:代码复用
缺点:高耦合github

三,高耦合的示例

看看Casa大神描述的场景编程

四,使用要点

1,父类只给子类提供服务,并不涉及子类的业务逻辑
2,层级关系明显,功能划分清晰,父类和子类互不干扰
3,父类的全部变化都须要在子类中体现,此时耦合已经成为需求
4,不宜超过2层,第3层继承是滥用的开端bash

5,做为一个开发人员,有一个交流学习的圈子是很重要的。如今小编这边有一个学习交流群(810733363)。欢迎你们进入交流学习。学习


五,使用场景

1,继承系统类库,好比自定义UITableViewCell
2,把公共的属性和方法放入父类中ui

@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
- (void)eat;
@end

// Man
@interface Man : Person
@end

@implementation Man
- (void)eat {
    NSLog(@"man eat");
}
@end

// Woman
@interface Woman : Person
@end

@implementation Woman
- (void)eat {
    NSLog(@"woman eat");
}
@end

// 使用
Man *man = [Man new];
man.name = @"111";
[man eat];

Woman *woman = [Woman new];
woman.name = @"222";
[woman eat];
复制代码
六,Super简单介绍

super的本质跟runtime有关,详细的放在runtime系列中进行讲解atom

1,在子类的init方法中必须调用[super init],由于在初始化子类以前必须先初始化父类spa

- (instancetype)init {
    self = [super init];
    if (self) {
    }
    return self;
}
复制代码

2,若是父类的某个方法没有实现,在子类的此方法中不能调用[super method],不然会crash3d

@implementation Person
@end

@implementation Man
- (void)eat {
    [super eat]; // crash
    NSLog(@"man eat");
}
@end
复制代码

3,若是父类的某个方法实现了,在子类的此方法中看状况调用[super method],若是须要用到父类的代码就调用,若是不须要就不调用,直接覆盖便可

@implementation Person
- (void)eat {
    NSLog(@"person eat");
}
@end

@implementation Man
- (void)eat {
    [super eat];
    NSLog(@"man eat");
}
@end
复制代码

4,重写系统的方法通常都须要调用[super method],由于系统内部作了不少初始化的工做

- (void)viewDidLoad {
    [super viewDidLoad];
}
复制代码

5,在子类的某个方法中调用[super method],在父类该方法中的self实际上是子类的对象

@implementation Person
- (NSString *)name {
    return @"111";
}
- (void)eat {
    NSLog(@"person %@ eat", self.name);
    NSLog(@"person: %@", self);
}
@end

@implementation Man
- (NSString *)name {
    return @"222";
}
- (void)eat {
    [super eat];
    NSLog(@"man %@ eat", self.name);
    NSLog(@"man: %@", self);
}
@end

// 使用
Man *man = [Man new];
[man eat];

// 打印
person 222 eat // 不是111
person: <Man: 0x6000012f2e90>  // 不是Person
man 222 eat
man: <Man: 0x6000012f2e90>
复制代码
七,替代方案

若是想达到代码复用而且可以解耦的效果,能够考虑下列几种方案

1,协议:把公共方法放入协议中(一般会放在父类中)

@protocol PersonProtocol <NSObject>
- (void)eat;
@end

// Man
@interface Man : NSObject <PersonProtocol>
@end

@implementation Man
- (void)eat {
    NSLog(@"man eat");
}
@end

// Woman
@interface Woman : NSObject <PersonProtocol>
@end

@implementation Woman
- (void)eat {
    NSLog(@"woman eat");
}
@end
复制代码

2,代理:自定义公共方法(一般把公共方法放入父类中,再在子类中自定义)

@protocol PersonDelegate <NSObject>
- (void)personStartEat;
@end

// Person
@interface Person : NSObject
@property (nonatomic, weak) id<PersonDelegate> delegate;
- (void)eat;
@end

@implementation Person
- (void)eat {
    if ([self.delegate respondsToSelector:@selector(personStartEat)]) {
        [self.delegate personStartEat];
    }
}
@end

// 使用
@interface ViewController () <PersonDelegate>
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    
    Person *person = [Person new];
    person.delegate = self;
    [person eat];
}

- (void)personStartEat {
    NSLog(@"每一个使用Person的类均可以自定义此方法");
}
@end
复制代码

3,组合:看看Casa大神是如何使用的

4,AOP(面向切面编程):把每一个控制器公共的操做抽取出来统一处理(一般会放在BaseViewController中)

@implementation ViewControllerConfigure
+ (void)load {
    [ViewControllerConfigure sharedInstance];
}
+ (instancetype)sharedInstance {
    static ViewControllerConfigure *_sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedInstance = [[ViewControllerConfigure alloc] init];
    });
    return _sharedInstance;
}
- (instancetype)init {
    if (self = [super init]) {
        // 拦截全部控制器的viewDidLoad方法
        [UIViewController aspect_hookSelector:@selector(viewDidLoad)
                                  withOptions:AspectPositionAfter
                                   usingBlock:^(id<AspectInfo> aspectInfo) {
                                       [self viewDidLoad:aspectInfo.instance];
                                   }
                                        error:nil];
    }
    return self;
}
- (void)viewDidLoad:(UIViewController *)viewController {
    NSLog(@"能够在这里统一处理");
}
@end
复制代码

第三方库Aspects的地址

八,多继承

虽然OC不支持多继承,但能够经过下列几种方案间接的实现

1,协议

@protocol Father <NSObject>
- (void)handsome;
@end

@protocol Mather <NSObject>
- (void)beautiful;
@end

@interface Son : NSObject <Father, Mather>
@end

@implementation Son
- (void)handsome {
    NSLog(@"帅气的");
}
- (void)beautiful {
    NSLog(@"美丽的");
};
@end
复制代码

2,组合

@interface Father : NSObject
- (void)handsome;
@end

@interface Mather : NSObject
- (void)beautiful;
@end

// Son
@interface Son : NSObject
- (void)handsome;
- (void)beautiful;
@end

@interface Son ()
@property (nonatomic, strong) Father *father;
@property (nonatomic, strong) Mather *mather;
@end

@implementation Son
- (instancetype)init {
    self = [super init];
    if (self) {
        _father = [Father new];
        _mather = [Mather new];
    }
    return self;
}
- (void)handsome {
    [_father handsome];
}
- (void)beautiful {
    [_mather beautiful];
}
@end
复制代码

3,消息转发

消息转发流程
  • 快速消息转发
@interface Father : NSObject
- (void)handsome;
@end

@implementation Father
- (void)handsome {
    NSLog(@"帅气的");
}
@end

// Mather
@interface Mather : NSObject
- (void)beautiful;
@end

@implementation Mather
- (void)beautiful {
    NSLog(@"美丽的");
};
@end

// Son
@interface Son : NSObject
- (void)handsome;
- (void)beautiful;
@end

@interface Son ()
@property (nonatomic, strong) Father *father;
@property (nonatomic, strong) Mather *mather;
@end

@implementation Son
- (instancetype)init {
    self = [super init];
    if (self) {
        _father = [Father new];
        _mather = [Mather new];
    }
    return self;
}
// 告诉系统把消息转发给哪一个对象
- (id)forwardingTargetForSelector:(SEL)aSelector {
    if ([_father respondsToSelector:aSelector]) {
        return _father;
    } else if ([_mather respondsToSelector:aSelector]) {
        return _mather;
    }
    return nil;
}
@end

// 使用
Son *son = [Son new];
[son handsome];
[son beautiful];

// 打印
帅气的
美丽的
复制代码
  • 标准消息转发
@implementation Son
- (instancetype)init {
    self = [super init];
    if (self) {
        _father = [Father new];
        _mather = [Mather new];
    }
    return self;
}
// 先对方法从新签名
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
    NSMethodSignature *signature = [super methodSignatureForSelector:aSelector];
    if (signature == nil) {
        if ([_father respondsToSelector:aSelector]) {
            signature = [_father methodSignatureForSelector:aSelector];
        } else if ([_mather respondsToSelector:aSelector]) {
            signature = [_mather methodSignatureForSelector:aSelector];
        }
    }
    return signature;
}
// 再转发消息
- (void)forwardInvocation:(NSInvocation *)anInvocation {
    SEL sel = [anInvocation selector];
    if ([_father respondsToSelector:sel]) {
        [anInvocation invokeWithTarget:_father];
    } else if ([_mather respondsToSelector:sel]) {
        [anInvocation invokeWithTarget:_mather];
    }
}
@end复制代码

来源:本文为第三方转载,若有侵权请联系小编删除。

相关文章
相关标签/搜索