我們知道 Objective-C 沒有抽象類。它并不像 C++/Java 那樣有專門的 abstract class 定義,但這并不妨礙你在用 Objective-C 寫程序的時(shí)候使用 "abstract class" 這一通用的 OOP 概念领猾,即類的部分實(shí)現(xiàn)需要subclass 來(lái)完成。
只根據(jù)抽象類中定義的接口來(lái)操縱對(duì)象有以下兩個(gè)好處:
1、客戶無(wú)須知道他們使用對(duì)象的特定類型珍德,只需要知道對(duì)象有客戶所期望的接口。
2矗漾、客戶無(wú)須知道他們使用對(duì)象是用什么類型來(lái)實(shí)現(xiàn)的锈候,只需要知道定義接口的抽象類。
這將極大地減少子系統(tǒng)實(shí)現(xiàn)之間的相互依賴關(guān)系敞贡,也產(chǎn)生了可服用的面相對(duì)象原則:針對(duì)接口編程泵琳,而不是針對(duì)實(shí)現(xiàn)編程。
這里提供以下兩種方式實(shí)現(xiàn)特殊的抽象類
方案一(利用 doesNotRecognizeSelector 報(bào)錯(cuò)方式):
AbstractObject.h
@interface AbstractObject : NSObject
// 抽象方法
- (double)calculateArea;
@end
AbstractObject.m
@implementation AbstractObject
- (instancetype)init {
// 注意這里不能使用 isKindOfClass
if ([self isMemberOfClass:[AbstractObject class]]) {
[self doesNotRecognizeSelector:_cmd];
return nil;
} else {
// 只有實(shí)例化子類誊役,調(diào)用 [super init] 才會(huì)走這邊
self = [super init];
if (self) {
/// 初始化操作
return self;
}
}
return nil;
}
- (double)calculateArea {
[self doesNotRecognizeSelector:_cmd];
return 0;
}
@end
測(cè)試:
@interface Rectangle : AbstractObject
@property (nonatomic, assign) double width;
@property (nonatomic, assign) double height;
@end
@implementation Rectangle
- (double)calculateArea {
return self.width * self.height;
}
@end
- (void)viewDidLoad {
[super viewDidLoad];
Rectangle *rectangle = [[Rectangle alloc] init];
rectangle.width = 10;
rectangle.height = 20;
NSLog(@"rectangle calculateArea = %f", [rectangle calculateArea]);
AbstractObject *object = [[AbstractObject alloc] init];
NSLog(@"AbstractObject calculateArea = %f", [object calculateArea]);
}
運(yùn)行結(jié)果:
方案二(斷言方式):
#define MethodNotImplemented() \
@throw [NSException exceptionWithName:NSInternalInconsistencyException \
reason:[NSString stringWithFormat:@"You must override %@ in a subclass.", NSStringFromSelector(_cmd)] \
userInfo:nil]
@implementation AbstractClass
- (id)init {
NSAssert(![self isMemberOfClass:[AbstractClass class]], @"AbstractClass is an abstract class, you should not instantiate it directly.");
return [super init];
}
// 抽象方法
- (double)calculateArea {
MethodNotImplemented();
return 0;
}
總結(jié):
類繼承是一個(gè)通過復(fù)用父類功能而擴(kuò)展應(yīng)用功能的基本機(jī)制获列。它允許你根據(jù)舊對(duì)象快速定義新對(duì)象。它允許你從已知存在的類中繼承所需要的絕大部分功能蛔垢,從而幾乎無(wú)須任何代價(jià)就可以獲得的新的實(shí)現(xiàn)蛛倦。
然而,實(shí)現(xiàn)復(fù)用只是成功的一半啦桌,繼承所擁有的定義具有相同接口的對(duì)象族的能力也是很重要的(通乘莺可以從抽象類來(lái)繼承)。
當(dāng)繼承被適當(dāng)使用時(shí)甫男,所有從抽象類導(dǎo)出的類將共享該抽象類的接口且改。這意味子類僅僅添加或重定義操作,而沒有隱藏父類的操作板驳。這時(shí)又跛,所有的子類都能相應(yīng)抽象類接口中的請(qǐng)求,從而子類的類型都是抽象類的子類若治。