1. 概念
多种形态,变量的多种形态。
对于一个引用变量(指针)变量,可以指向任何子类的对象。也可以指向本类型的对象。对于同一个引用(指针),指向对象的类型不同,当通过该引用(指针)发送消息时,调用的方法会完全不同,此时方法的调用时多态的。
2. 编译器类型和运行期类型
在多态下,父类的引用可以指向任何自类的对象。但当编译器编译程序时,编译器无法确定引用指向的对象是什么类型,所以编译器会将引用当做父类的类型做编译检查,如果调用的方法父类中没有,则编译警告。但程序运行期间,通过父类的引用向子类对象发送消息时,调用的却是子类的方法。
TRAnimal *a =[[TRAnimal alloc]init]; 编译时,将a当做 TRAnimal类型来看,叫编译期类型。运行时,系统将a当做TRDog类型来看,叫运行期类型。
3. 多态的好处
可以让我们设计出更加合理的架构,写出更加通用的程序,提高程序的可维护性和可扩展性。
4. 多态的表现
1).多态在方法的参数上的表现
假设在主函数中定义了
void show(TRAnimal *a) {
[a sleep];
[a eat];
}
方法, 则一下程序:
TRDog *dog =[[TRDog alloc]init];
TRCat *cat =[[TRCat alloc]init];
show(dog); //调用TRDog类中的sleep 和 eat 方法
show(cat); //调用TRCat类中的sleep 和 eat 方法
都是正确的,这样就使得show方法变得更加通用化,因为只要是TRAnimal的子类,都可以使用此方法,而且只会调用相应的子类方法,不会是程序出错。
2). 多态在返回值上的表现
typedf enum Animals{
ANIMAL,
DOG,
CAT,
}Animals;
TRAnimal* get(Animals type)
{
if (type ==ANIMAL ){
return [[[TRAnimal alloc]init]autorelease];
}else if (type ==DOG){
return [[[TRDog alloc]init]autorelease];
}else if ( type == CAT) {
return [[[TRCat alloc]init]autorelease];
}
return nil;
}
这样,虽然get函数的类型是TRAnimal类型的,但是返回值可以是TRDog类型,或者TRCat类型的。这就是在返回值上的多态。
3). 在数组或者集合上的表现
void test()
{
TRAnimal *as[5];
as[0] = [[TRDog alloc]init];
as[1] = [[TRCat alloc]init;
as[2] = [[TRAnimal alloc]init];
for(int i=0;i<5;i++){
[as[i] eat]; }
}
这样就会执行相应的类里的eat方法。这样就能使程序变得更加容易扩展,移植,而且大大加强了代码的通用性。