OC:繼承和多型碰到的坑
阿新 • • 發佈:2018-12-12
今天(2018.12.5)算是正式開始學OC了,加油!
#import <UIKit/UIKit.h> #import "AppDelegate.h" @interface A : NSObject - (void) whoAreYou; @end @implementation A - (void) whoAreYou { printf("AAA\n"); } @end @interface B : A - (void) sayHello; @end @implementation B - (void) whoAreYou { printf("BBB\n"); } - (void) sayHello { printf("Hello\n"); } @end int main(int argc, char * argv[]) { A *a, *b; // 編譯器希望a和b都指向A型別的記憶體空間 a = [[A alloc] init]; b = [[B alloc] init]; // 然而我讓b指向B型別的型別空間,好在B是A的子類,所以共享了部分記憶體,不會報錯 [a whoAreYou]; [b whoAreYou]; // 呼叫的是B過載的whoAreYou函式 [(B *)b sayHello]; // 此時b的型別是A*,但是他想呼叫A這片記憶體之外的的函式(即sayHello),則應該強制型別轉換成B*型別,倘若他就想呼叫父類的方法,就沒必要強轉。 // [(B *)a sayHello]; // 這句話會報錯,父類的型別不能強轉成子類的型別,但是子類的型別可以強轉成父類的型別 }
如果b就想呼叫父類的方法,就沒必要強轉,因為b目前的型別是A *,是可以指向父類的記憶體的,因此不會報錯,程式碼如下,則B就不用重寫函數了,程式碼如下:
#import <UIKit/UIKit.h> #import "AppDelegate.h" @interface A : NSObject - (void) whoAreYou; @end @implementation A - (void) whoAreYou { printf("AAA\n"); } @end @interface B : A - (void) sayHello; @end @implementation B //- (void) whoAreYou { // printf("BBB\n"); //} - (void) sayHello { printf("Hello\n"); } @end int main(int argc, char * argv[]) { A *a, *b; // 編譯器希望a和b都指向A型別的記憶體空間 a = [[A alloc] init]; b = [[B alloc] init]; // 然而我讓b指向B型別的型別空間,好在B是A的子類,所以共享了部分記憶體,不會報錯 [a whoAreYou]; [b whoAreYou]; // 呼叫的是父類的函式,不必強轉 [(B *)b sayHello]; // 此時b的型別是A*,但是他想呼叫A這片記憶體之外的的函式(即sayHello),則應該強制型別轉換成B*型別,倘若他就想呼叫父類的方法,就沒必要強轉。 // [(B *)a sayHello]; // 這句話會報錯,父類的型別不能強轉成子類的型別,但是子類的型別可以強轉成父類的型別 }
又發現一個好玩的,來證明父類的型別不能強轉成子類的
#import <UIKit/UIKit.h> #import "AppDelegate.h" @interface A : NSObject - (void) whoAreYou; @end @implementation A - (void) whoAreYou { printf("AAA\n"); } @end @interface B : A - (void) sayHello; @end @implementation B - (void) whoAreYou { printf("BBB\n"); } - (void) sayHello { printf("Hello\n"); } @end int main(int argc, char * argv[]) { A *a, *b; // 編譯器希望a和b都指向A型別的記憶體空間 a = [[A alloc] init]; b = [[B alloc] init]; // 然而我讓b指向B型別的型別空間,好在B是A的子類,所以共享了部分記憶體,不會報錯 [(B *)a whoAreYou]; // 我讓a強轉成(B*),輸出的竟然是AAA,說明強轉失敗啦,還是那句話,父類的型別不能強轉成子類的 //[(B *)a sayHello]; // 這句話會報錯,因為不能強轉 }
引入一個id型別的看看?
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
@interface A : NSObject
- (void) whoAreYou;
@end
@implementation A
- (void) whoAreYou {
printf("AAA\n");
}
@end
@interface B : A
- (void) sayHello;
@end
@implementation B
- (void) whoAreYou {
printf("BBB\n");
}
- (void) sayHello {
printf("Hello\n");
}
@end
@interface C : NSObject
- (void) printName;
@end
@implementation C
- (void) printName {
printf("shijie");
}
@end
int main(int argc, char * argv[]) {
A *a, *b; // 編譯器希望a和b都指向A型別的記憶體空間
id c;
a = [[A alloc] init];
b = [[B alloc] init]; // 然而我讓b指向B型別的型別空間,好在B是A的子類,所以共享了部分記憶體,不會報錯
c = [[C alloc] init];
[c printName];
}