OC语言 - 面向对象:多态
■ 前言
要使用多态就必须要有继承,没有继承就没有多态!多态在代码中的体现就是允许父类指针指向子类对象
OC 使用多态时会自行动态检测,以调用真实的对象方法
■ 使用多态
1. 下面是一个简单的多态
// - Animal.h :只有一个干饭的方法
1 #import <Foundation/Foundation.h> 2 3 @interface Animal : NSObject 4 5 - (void)eat; 6 7 @end
// - Animal.m
1 #import "Animal.h" 2 3 @implementation Animal 4 5 - (void)eat{ 6 7 NSLog(@"--%@吃东西--",self); 8 } 9 @end
// - Dog.h :继承自 Animal,但自身同样存在一个干饭的方法
#import "Animal.h" @interface Dog : Animal - (void)eat; @end
// - Dog.m
1 #import "Dog.h" 2 3 @implementation Dog 4 5 - (void)eat{ 6 7 NSLog(@"==%@吃东西==",self); 8 } 9 10 @end
// - main.m
1 #import <Foundation/Foundation.h> 2 #import "Animal.h" 3 #import "Dog.h" 4 int main(int argc, const char * argv[]) { 5 @autoreleasepool { 6 7 Dog *dg = [[Dog alloc] init]; 8 [dg eat]; // 执行 Dog eat 方法 9 Animal *ani = [[Animal alloc] init]; 10 [ani eat]; // 执行 Animal eat 方法 11 12 // 使用多态 13 Dog *dg01 = [[Dog alloc] init]; 14 [dg01 eat] 15 Animal *ani0 = [[Dog alloc] init];// 父类指针指向子类对象 16 [ani0 eat];// 执行的是 Dog eat 方法 17 18 // 错误使用 19 NSObject *n01 = [[Dog alloc] init]; 20 NSObject *n02 = [[Animal alloc] init]; 21 //[n01 eat];// 标记一 22 } 23 return 0; 24 }
2. 使用场景:比如现在要喂养 n 只不同种小动物。在没使用多态时喂一只狗,那么就要给定一个函数来实现喂狗的功能
void feed(Dog *d){ [d eat];
}
假如你还要喂猫,于是又要新写一个函数来实现养猫的功能
void feed(Cat *c){ [c eat]; }
如果你还要喂猪、喂羊、喂马.......其实不论什么动物它们都继承自 Animal 这一共性。那么我们在这里就可以考虑使用多态
// 没有使用多态 void feedDog(Dog *dog){ [dog eat]; } // 使用了多态 void feedAnimal(Animal *ani){ [ani eat]; } int main(int argc, const char * argv[]) { @autoreleasepool { Animal *ani0 = [[Dog alloc] init]; feedAnimal(ani0);// OC 会自动检测并执行 Dog 中的对象方法 } return 0; }
注:使用多态时父类类型的指针不能直接调用其子类独有的方法(父无子有),这就是 标记一 的原因
Animal *a=[[Dog alloc] init]; [a run];// Animal 中没有 run 方法的且只有 Dog 中存在 run 方法!程序报错
解决方式:强转换下指针即可
Dog *d=(Dog *)a;// 此时的 a 和 d 指向的是同一个对象,即 Dog 实例对象
■ 多态的优缺点
1. 好处
如果函数方法参数中使用的是父类类型,则可以传入父类和子类对象,而不用再去定义多个函数来和相应的类进行匹配
不同子类对象当作父类来看,可达到屏蔽子类对象之间的差异、写出通用的代码、使程序更加灵活的目的
2. 坏处
父类类型的变量不能直接调用子类独有的方法,如果一定要调用则必须强制转换为子类后才能进行