------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
1、设计一个类
#inport<Foundation/Foundation.h>
//声明
@interface Animal :NSObject
-(void)eat;
@end
@implementation Animal
//方法的实现
-(void)eat
{
NSObject(@"Animal eat");
}
@end
@interface Dog :Animal
@end
@implementation Dog
-(void)eat
{
NSObject(@"Dog eat");
}
@end
@interface Cat :Animal
@end
@implementation Cat
-(void)eat
{
NSObject(@"Cat eat");
}
@end
void feed(Dog *d)
{
[d eat];
}
int main()
{
//多态:父类指针指向子类对象
Animal *a = [Animal new];
//当调用方法时,会检测对象的真时类型
[a eat];
}
输出结果:Dog eat
所以,NSObject *a = [Animal new];
NSObject *b = [Dog new];
都是多态,当调用方法时会检测真实类型
但 Dog *a = [Animal new]; 和 子类之间:Dog *a = [Cat new];
和 没有父子关系的:NSstring *a = [Dog new]; 不会报错,只有警告
弱语法的体现,但都不合理。
2、把main改为:
int main()
{
Dog *dd = [Dog new];
feed(dd);
}
输出结果:Dog eat
3、把main改为:
int main()
{
Cat *cc = [Cat new];
//feed(cc);
}
这样写不行,因为feed定义时是(Dog *d),所以要想输出Cat eat可能会想再加一个feed
void feed1(Cat *c)
{
[c eat];
}
这样mai函数里写:feed1(cc);就行,这样写可以,但太冗余
所以,把feed 与 feed1改为一个feed函数:
void feed(Animal *a)
{
[a eat];
}
int main()
{
Dog *dd = [Dog new];
feed(dd);
Cat *cc = [Cat new];
feed(cc);
Animal *aa = [Animal new];
feed(aa);
}
输出结果:Dog eat
Cat eat
Animal eat
所以,如果参数中使用的是父类类型,可以传入父类、子类对象
若在Dog中声明和实现-(void)run方法
{
NSLog(@"Dog run");
}
则main函数中:
{
Animal *aa = [Dog new];
[aa run];
}
输出结果:编译有警告
因为Animal没有run方法,但一样能输出Dog run
所以多态的局限性:父类类型的变量不能用来调用子类的方法。
不建议用这种方法。
可以强制类型转换
{
Animal *aa = [Dog new];
Dog *dd =(Dog *)aa;
[dd run];
}
输出结果:Dog run
其中Dog *dd =(Dog *)aa;这句语句是强制类型转换(Dog *)是做给编译器看的,这句等价于Dog *dd = aa;
但这样写不合理,aa是Animal型的,赋给Dog型的,不合理。
所以需Dog *dd =(Dog *)aa这样写。
4、总结:
1.没有继承就没有多态
2.代码的体现:父类类型的指针指向子类对象
3.好处:如函数\方法参数中使用的是父类类型,可传入父类、子类对象
4.局限性:
1>父类类型的变量不能直接调用
2>子类特有的方法,必须强转换为子类类型变量后,才能直接调用子类特有的方法
5、以下是弱语法的体现,不要这样写,容错能力太强
{
Dog *d = [Cat new];
[d eat];
}
编译时有警告,运行时出结果:Cat eat
{
NSstring *d = [Cat new];
[d eat];
}
编译时有警告,运行时出结果:Cat eat