面向对象的多态是建立在继承上,可以说没有继承就没有多态;
多态:父类指针指向了子类的对象;
1 int main() 2 { 3 //假设已定义了Animal类和它的子类Dog,那么多态的代码体现就是 4 Animal *a = [Dog d];//父类指针指向了子类对象 5 6 }
多态的定义是比较简单的,也好理解,关键在于它的指针动态绑定,究竟调用哪个方法;
1 #import <Foundation/Foundation.h> 2 3 //Animal类的声明 4 @interface Animal : NSObject 5 { 6 int _legs; 7 } 8 9 - (void)eat; 10 - (void)run; 11 @end 12 13 //Animal类的实现 14 @implementation Animal 15 - (void)eat 16 { 17 NSLog(@"动物在吃东西"); 18 19 } 20 21 - (void)run 22 { 23 NSLog(@"动物在跑"); 24 } 25 26 @end 27 28 //子类Dog 继承 Animal 29 @interface Dog : Animal 30 31 @end 33 //子类dog的实现 34 @implementation Dog 35 //方法的覆盖或叫重写 36 - (void)eat 37 { 38 NSLog(@"狗在吃东西"); 40 } 41 @end 42 43 int main() 44 { 45 46 Animal *a = [Dog new];//虽然表面上是一个Animal指针,但是动态绑定后,实际上它指向的是Dog类型的 47 [a eat];//动态绑定后,输出的时狗在吃东西,即狗的eat方法 48 49 }
这样就看到了多态的好处,当有两个方法的参数都是对象,且有共同的父类时,这两个方法可以写成一个方法,只需把参数改为父类对象就可以了
//已经定义了Dog,Cat两个类,他们都继承了Animal方法,且定义了eat方法,子类都重写了eat方法 //喂猫吃东西的方法 void catEat(Cat *c) { [c eat]; } //喂狗吃东西的方法 void dogEat(Dog *d) { [d eat]; } /******那么这两个方法就比较冗余了,可以用一个方法代替*******/ void animalEat(Animal *a) { [a eat]; }
虽然多态用起来减少了代码的冗余,但是由于OC弱类型编程语言的容错能力强,局限性也很明显
1:父类对象不能调用子类的特有方法,但是真得调用了,也只是一个警告,照样能够运行起来;可以用类型转换,将父类对象转成子类的对象
语法:
Animal *aa = [Dog new];
//注意强转的格式带*号 Dog *dd = (Dog *)aa;//这里的强转也只是给编译器看得,不写,也能运行,只不过编译时一个警告;
2:一个类的指针能指向一个和本类好无关系的对象,编译只是一个警告,照样能调用其中的方法;
NSString *ns = [Dog new]; [ns eat];//只是警告,但是能运行,不建议这样写;