什么是多态?
官方说法:同一接口,不同实现方法。其实大白话就是(以父类和子类为例,实际上可以不限于这种关系):父类有一个方法(函数),派生出得很多子类也有这个方法(函数),但是每个方法(函数)里内容不同。当然方法相同是指这个方法的名字、返回值类型、参数个数类型都一样。
直接上例子:我们创建一个父类ASShape有个draw方法,派生出三个子类ASCircle,ASRectangle、ASTriangle各自也有一个draw,当然每个draw里内容不同,就是实现输出一个句子。
(1)先创建一个父类:
//ASShape.h文件 #import <Foundation/Foundation.h> @interface ASShape : NSObject -(void)draw; @end //ASShape.m文件 #import <Foundation/Foundation.h> @interface ASShape : NSObject -(void)draw; @end
(2)再创建三个子类,draw方法相同,里面内容不同,以下只列出一个,另外的ASCircle类和ASRectangle类自己冥想去。
//ASTriangle.h文件,继承ASShape类 #import "ASShape.h" @interface ASTriangle : ASShape -(void)draw; @end //基本和父类ASShape的draw类似,只是内容输出不同 #import "ASTriangle.h" @implementation ASTriangle -(void)draw{ NSLog(@"triangle:draw"); } @end
(3)再创建一个ASPerson类,借助这个类的paint方法把上面的类当做参数,并调用它们各自的draw方法
//ASPerson.h,要使用ASShape类,因为下面会用它创建对象 #import <Foundation/Foundation.h> @class ASShape; @interface ASPerson : NSObject -(void)paint:(ASShape *)aShape; @end //ASPerson.m,需要导入各个头文件,不然它们各自的draw函数根本不能会调出来 #import "ASPerson.h" #import "ASShape.h" #import "ASCircle.h" #import "ASRectangle.h" #import "ASTriangle.h" @implementation ASPerson -(void)paint:(ASShape *)aShape{ [aShape draw]; } @end
(4)最后在main.m里面创建对象,并用这个对象去调用paint方法,由于paint方法的参数是ASShape类的对象,本应该调用ASShape类对象自己的draw函数,但是因为我们把ASShape子类实例化的对象当做参数传递给了paint,所以它们调用的就是各个子类自己的draw函数。这应该就是因为draw是多态的,所以调用哪个取决于你传递的参数吧。
#import <Foundation/Foundation.h> #import "ASPerson.h" #import "ASShape.h" #import "ASCircle.h" #import "ASRectangle.h" #import "ASTriangle.h" int main(int argc, const char * argv[]) { @autoreleasepool { ASPerson * person=[[ASPerson alloc]init]; ASCircle * circle=[[ASCircle alloc]init]; ASRectangle * rec=[[ASRectangle alloc]init]; ASTriangle * tri=[[ASTriangle alloc]init]; [person paint:circle]; [person paint:rec]; [person paint:tri]; } return 0; }
(5)运行结果
circle:draw rectangle:draw triangle:draw
注意事项:
a:把父类指定换成id通用指针,运行结果一样OK。id通用指针可以指向任何对象,指向谁就调用谁的方法(函数)。
@implementation ASPerson -(void)paint:(id)aShape{ [aShape draw]; } @end
b:我们创建一个不集成ASShape的类叫ASExp,也给它定义一个draw方法。和上面操作步骤一致,先实例化一个对象对来,然后如下,发现结果也能输出,也就是说,这个多态并非一定要是父类和子类之间。
ASExp * exp=[[ASExp alloc]init]; [person paint:exp];
如果没有这个父类和子类的限制,或许能更明白多态,多态其实就是一个方法(函数)在不同类中写了很多个,具体执行时候,传递的时哪个类对象,就调用那个类对象的方法(函数)。