前言:
oc中的指針類型變量有兩個:一個是編譯時類型,一個是運行時類型,編譯時類型由聲明該變量是使用的類型決定,運行時類型由實際賦給該變量的對象決定。如果編譯時類型和運行時類型不一致,就有可能出現多態。
正文:
新建一個CHPerson類
1 @interface CHPerson : NSObject 2 -(void)eat; 3 -(void)play; 4 @end
5 ---------------------------------------------------------
6 #import "CHPerson.h"
7
8 @implementation CHPerson 9 -(void)eat{ 10 NSLog(@"----父類的吃"); 11 } 12 -(void)play{ 13 NSLog(@"-----父類的玩"); 14 } 15 @end
新建一個繼承於CHPerson的CHchina類
1 #import "CHPerson.h"
2
3 @interface CHChina : CHPerson 4 -(void)playgame; 5 @end
6
7 ----------------------------------------------------
8
9 #import "CHChina.h"
10
11 @implementation CHChina 12 -(void)eat{ 13 NSLog(@"=======子類的吃"); 14 } 15 -(void)playgame{ 16 NSLog(@"玩游戲"); 17 } 18 @end
調用方法:
1 #import "ViewController.h"
2 #import "CHChina.h"
3 @interface ViewController () 4
5 @end
6
7 @implementation ViewController 8
9 - (void)viewDidLoad { 10 [super viewDidLoad]; 11 // 下面編譯時類型和運行時類型完全一樣,因此不存在多態
12 CHPerson *person = [[CHPerson alloc]init]; 13 [person eat]; 14
15 // 下面編譯時類型和運行時類型完全一樣,因此不存在多態
16 CHChina *china = [[CHChina alloc]init]; 17 [china eat]; 18
19 // 下面編譯時類型和運行時類型不一樣,因此發生多態
20 CHPerson *perch = [[CHChina alloc]init]; 21 // 調用從父類繼承的play方法
22 [perch play]; 23 // 調用子類重寫eat方法
24 [perch eat]; 25
26 // 因為perch的編譯時類型是CHPerson,但CHPerson沒有playgame方法,所以編譯時會報錯 27 // [perch playgame]; 28 // 但可以將任何類型的指針變量賦值給id類型的變量
29 id allperch = perch;//下面會解釋為何這樣做? 30 [allperch playgame]; 31
32 }
結果:
1 2015-10-01 17:54:03.705 多態[86274:361586] ----父類的吃 13行代碼結果 2 2015-10-01 17:54:03.705 多態[86274:361586] =======子類的吃 3 2015-10-01 17:54:03.706 多態[86274:361586] -----父類的玩 4 2015-10-01 17:54:03.706 多態[86274:361586] =======子類的吃 24行代碼結果 5 2015-10-01 17:54:03.706 多態[86274:361586] 玩游戲
- 指針perch變量比較特殊,編譯是CHPerson類型,運行時是CHChina類型,所以實際上執行的是CHChina類中覆蓋后的eat方法。指針變量在編譯階段只能調用編譯時所具有的方法,但運行時則執行其運行時類型所具有的方法
- 子類其實是一種特殊的父類,oc中允許把一個子類對象直接賦值給一個父類指針變量,不需要任何變量。
- 當把一個子類對象直接賦值給一個父類指針變量時( CHPerson *perch = [[CHChina alloc]init];),編譯時和運行時類型不一樣,運行時調用該指針變量的方法時,其方法子類方法而不是父類的方法,這就出現了相同類型的變量調用同一個方法時呈現出多種不同行為特征。
補充(id):oc中提供了一個id類型,這個id類型可以代表所有對象的類型。就是說,任意類型的對象都可以賦值給id類型變量。
當通過id類型變量來調用方法時,oc將會執行動態綁定,動態綁定,是指oc將會跟蹤對象所屬類,它會在運行時判斷該對象所屬類,並在運行時確定需要動態調用的方法,而不是在編譯時確定要調用的方法。如上面,程序會在運行時動態檢測該變量所指的對象的實際類型為CHChina,所以會動態綁定到執行CHChina的eat方法。
