目錄
一,基本概念
二,優缺點
三,高耦合的示例
四,使用要點
五,使用場景
六,Super簡單介紹
七,替代方案
八,多繼承html
繼承、封裝、多態是面向對象的三大支柱。OC
只支持單繼承,父類能夠有多個子類,但子類有且僅有一個父類git
優勢:代碼複用
缺點:高耦合github
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
的本質跟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
複製代碼
雖然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複製代碼
來源:本文爲第三方轉載,若有侵權請聯繫小編刪除。