抽象基類
最開始的時候覺得有沒有什么辦法可以使得oc中也能夠有抽象基類,于是想了很多辦法,比如說斷言和異常,但是感覺自己對編程的認識程度不深,覺得還有沒有別的方案來實現(xiàn),一直查了很多資料都沒有更優(yōu)方案的實現(xiàn),有個小伙伴說他在sunnyxxx大神里面好像有看到過,然后給我說,應該是在方法后面寫一個宏:
// 注意:父類中的方法加`NS_REQUIRES_SUPER`,子類重寫才有警告提示
- (void)prepare NS_REQUIRES_SUPER;
開始的時候我以為是必須要重寫父類方法的警告,后面寫上去才發(fā)現(xiàn)應該描述為,必須要調用父類的這個方法進行初始化操作;
再然后,我也沒辦法就放棄了抽象基類的想法,后面我看到Masnory的作者在編寫MASConstraint抽象基類的時候,也是用了斷言的辦法:
- (id)init {
NSAssert(![self isMemberOfClass:[MASConstraint class]], @"MASConstraint is an abstract class, you should not instantiate it directly.");
return [super init];
}
然后在需要重寫的抽象方法里面加上一個宏的調用:
#define MASMethodNotImplemented() \
@throw [NSException exceptionWithName:NSInternalInconsistencyException \
reason:[NSString stringWithFormat:@"You must override %@ in a subclass.", NSStringFromSelector(_cmd)] \
userInfo:nil]
這樣就能想其他語言一樣定義了一個抽象基類了,但是我還是在想有沒有什么辦法,可以讓程序在編譯過程中就提示該類是抽象基類,必須重寫公開的方法,如果朋友們有什么特殊的獨門秘訣希望能和我分享一下,謝謝~
協(xié)議
協(xié)議在其他語言中也有被稱為接口之意,在iOS當中有此協(xié)議和代理之分,在某篇文章中看過一句話大概是這樣說的"協(xié)議這么好用的設計模式,你們居然只用來傳值太可惜了",原文比較偏激我就和諧一下吧.其實面向協(xié)議編程是一種提高代碼健壯性的方法之一,在設計模式當中,其實很多地方都會用到面向協(xié)議這個概念.
那么,面向協(xié)議有什么好處呢?其中最明顯的好處就是針對接口,而不是針對實現(xiàn)去編程,由于我們的業(yè)務可能有很多改動的需要,所以如果只是針對實現(xiàn)去編程的話,可能業(yè)務擴展或者修改的時候,我們就要修改更多的內容去適應變動,比如原來是使用AFN作為網絡請求的庫,現(xiàn)在領導說要用ASI,這個時候,如果當初寫的是面向接口編程的話,修改起來可能就只需要修改實現(xiàn)類就可以了.協(xié)議能夠大大降低程序的耦合度.
#import <Foundation/Foundation.h>
@class SEContext;
@protocol SEOneDayState <NSObject>
-(void)handle:(SEContext*)context;
@end
@protocol是聲明協(xié)議的方法,里面的方法有@required(必須實現(xiàn))和@optional(可選實現(xiàn))
協(xié)議和抽象基類的區(qū)別于聯(lián)系
- 協(xié)議和抽象基類都需要子類重寫方法
- 推翻第一條結論,由于抽象基類可以抽取高度相同的方法避免重寫多寫(一般成為默認行為),所以抽象基類重復使用的代碼部分可以不重寫;
- 抽象基類可以有私有方法(基于第2條,可以抽取高度相同的方法);協(xié)議作為對外接口,一般都是公開方法,
- 協(xié)議沒有實現(xiàn),都是聲明;抽象基類可以有實現(xiàn),需要子類重寫的方法請拋異臣苯模或者斷言給使用者.
- 抽象基類和子類是繼承關系,協(xié)議和類是聲明關系,由于OC中類繼承是單繼承,而可以同時使用多個協(xié)議,所以各有各的優(yōu)點.
- 抽象類和接口都不能直接實例化匾寝,如果要實例化拉庶,抽象類變量必須指向實現(xiàn)所有抽象方法的子類對象(面向對象三大特性之一)咨演,接口變量必須指向實現(xiàn)所有接口方法的類對象(如:** id<Eatting,running> **)