我們知道面向?qū)ο笕筇匦苑庋b、繼承、多態(tài),然而OC我認為嚴格意義上來說不算是純面向?qū)ο笳Z言,例如它沒有構(gòu)造器的概念,它的多態(tài)性質(zhì)有一些奇怪的地方。Swift終于回歸正常,我以前做過java開發(fā),對比著思考,Swift語言面向?qū)ο笮再|(zhì)和java非常類似,下面我會舉個例子來對比OC和Swift多態(tài)的性質(zhì)。
在對比OC和Swift多態(tài)性質(zhì)之前,我先強調(diào)一下滿足多態(tài)的條件。
多態(tài)三要素:
1. 類繼承
2. 方法override
3. 父類對象指向子類
- 先看Swift實例
class A: NSObject {
override init() {
super.init()
bbb()
aaa() // 多態(tài)
}
func aaa() {
print("classA ------> aaa()")
}
private func bbb() {
print("classA ------> private bbb()")
}
}
// B繼承于
class B: A {
override init() {
super.init()
}
override func aaa() {
super.aaa()
print("classB ------> aaa()")
super.aaa()
}
private func bbb() {
print("classB ------> private bbb()")
}
}
這段實例代碼再簡單不過了,假如我們在外面調(diào)用B(),你覺得輸出結(jié)果是什么呢?
classA ------> private bbb()
classA ------> aaa()
classB ------> aaa()
classA ------> aaa()
看看你設想的輸出結(jié)果是否和答案一致,如果不一致的話,說明面向?qū)ο筮€領悟的不到位,需要繼續(xù)領悟。
- 那么接下來看一下奇葩的OC會是什么樣的結(jié)果
@interface A : NSObject
- (void)aaa;
@end
@implementation A
- (instancetype)init
{
if (self = [super init]) {
[self bbb]; // 重點思考:會調(diào)用哪???
[self aaa];
}
return self;
}
// public method
- (void)aaa
{
NSLog(@"classA ------> aaa()");
}
// privateMethod
- (void)bbb
{
NSLog(@"classA ------> private bbb()");
}
@end
// ================================================
@interface B : A
@end
@implementation B
- (instancetype)init
{
if (self = [super init]) {
}
return self;
}
// override
- (void)aaa
{
[super aaa];
NSLog(@"classB ------> aaa()");
[super aaa];
}
// privateMethod
- (void)bbb
{
NSLog(@"classB ------> private bbb()");
}
@end
這里我說明一下,注釋雖然標識了privateMethod,OC嚴格來說是沒有公有方法和私有方法這么一說的,全看.h是否暴露。這段OC代碼和上面的Swift代碼類似,那么在外面執(zhí)行[[B alloc] init]會有什么輸出結(jié)果呢?
classB ------> private bbb()
classA ------> aaa()
classB ------> aaa()
classA ------> aaa()
請仔細思考一下,在A的init方法中,[self bbb]為什么沒有調(diào)用自己,而是調(diào)用到子類中,然而類A中的bbb這個方法并沒有被子類override,正常的面向?qū)ο?,這里是不滿足多態(tài)的性質(zhì)的,類之間是有隔離的,應該調(diào)自己才是,然而OC會調(diào)到子類去了,這是因為OC是保存方法列表的,會在B類包過其父類所有方法列表去尋找往哪調(diào),所以就調(diào)到B里面的bbb方法中去了,設想一下,假如我們繼承一個第三方?jīng)]開源的一個類,在我們自己的類中寫了一個私有方法,這個時候恰好這個私有方法和父類重名,是不是有可能發(fā)生一些低概率的悲劇事件,也正是因此,我會覺得OC的面向?qū)ο笥悬c奇怪