前言:
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方法。
时间: 2024-10-27 00:06:44