- /**
- * 1.多态的理解
- 多态本是指事物的多种形态.(例如:水可以为液态水,固态冰,气态水蒸气)
- 代码中的体现为:父类的指针 指向了 子类的对象.
-
- 2.OC中多态的实现,前提是:
- (1)类与类之间有继承关系.
- (2)子类中有对父类中的方法进行了重写.
-
- 3.多态的好处:
- 如果函数或方法中的参数使用的是父类类型,则可以传入父类或者子类的对象,而不用定义多个函数或方法来匹配相应的类.
-
- 4.多态的局限性:
- 父类类型的变量不能直接调用子类中特有的方法.如果必须要调用,则必须先强制转换成子类,然后再近些调用.
-
- 说了这么多了,接下来进行具体的测试:
- 思路:
- 创建两个类(人类 和 学生类),具有继承关系,并且学生类新增了特有的属性和方法,并对人类中的一个方法进行了重写.
- 请先往下看,不着急看结论.
-
-
- 总结:
- (1)OC语言是一门弱语法语言,在创建对象时,编译器在编译时并不能检测真实类型,只能在运行时才能动态检测对象类型.
- (2)使用多态需要十分注意类与类之间的关系,子类本身所拥有的属性和方法就比父类多,并且子类拥有父类的所有属性和方法(包括重写的方法).
- (3)不同类之间的对象转换问题:本质上不是真正的一个对象转变成另一个对象(逻辑上或情理上也是不可能的).这样的转换只是告诉编译器我们进行
- 了类型的转换,实际上指针所指向的那块内存空间一直都没有变化.
- 第一种情况:当把子类对象强制转换成父类对象时,只是把子类对象所拥有的特有属性和方法暂时屏蔽了.一旦把转换成的父类对象,再次转换成子
- 类对象时又可以访问子类对象所拥有的特有属性和方法.
- 第二种情况:当把父类对象强制转换成子类对象时,其实我们是对编译器进行欺骗操作.让编译器误认为转换成的子类对象,真的是一个子类对象,本
- 质上它还是个父类对象.所以编译时不会报错,一旦执行子类对象所拥有的特有属性和方法时,就会造成程序的崩溃.
- */
- #import <Foundation/Foundation.h>
- #import "YYPerson.h"
- #import "YYStudent.h"
- int main(int argc, const char * argv[]) {
- @autoreleasepool {
-
- //1.直接创建一个父类对象
- YYPerson *p1 = [YYPerson new];
- [p1 eat];
- [p1 sleep];
- // [p1 study]; //父类对象不能调用子类中的方法
-
- //2.直接创建一个子类对象
- YYStudent *stu1 = [YYStudent new];
- [stu1 eat]; //子类对象可以直接调用父类中的对象方法
- [stu1 sleep]; //子类对象可以直接调用父类中的对象方法
- [stu1 study];
-
- //3.多态的实现
- YYPerson *p2 = [YYStudent new]; //此时:父类的指针指向了子类的对象
- [p2 eat]; //结果p2调用的是学生类中的 eat方法.
- [p2 sleep]; //由于没有方法的重写,p2调用的仍然是人类中的 sleep方法
- // [p2 study]; //父类类型的变量不能直接调用子类中特有的方法,不能通过编译.
-
- YYStudent *stu2 = (YYStudent *)p2; //把父类的对象强制转换成子类的对象
- [stu2 study]; //此时能调用子类中特有的方法 study方法
-
- //4.子类对象 强制转换成 父类对象
- YYStudent *stu3 = [YYStudent studentWithName:@"杰克" andAge:18 andNumber:@"5201314" andScore:100];
- YYPerson *p3 = (YYPerson *)stu3;
- [p3 eat]; //调用是学生中 eat方法
- [p3 sleep]; //调用的是人类中的 sleep方法
- // [p3 study]; //不能调用 --编译器直接报错
- NSLog(@"stu3 address = %p",stu3); //stu3 address = 0x1005006a0
- NSLog(@"p3 address = %p",p3); //p3 address = 0x1005006a0
- /**
- * 结论:OC中可以把子类对象强制转换成父类对象,其实这两个指针 指向了同一地址.并且转换成父类对象后,不能再调用子类中特有的属性和方法.
- */
-
-
- //5.父类对象 强制转换成 子类对象
- YYPerson *p4 = [YYPerson personWithName:@"汤姆" andAge:32];
- YYStudent *stu4 = (YYStudent *)p4;
- [stu4 eat]; //调用的是人类中的 eat方法
- [stu4 sleep]; //调用的是人类中的 sleep方法
- // [stu4 study]; //编译器不会报错,但是在执行时会崩溃,会告诉找不到 study方法.
- /**
- * 结论:OC中不可以把父类对象强制转换成子类对象,对编译器进行了欺骗操作,一旦访问了子类中特有的属性或者方法,就会导致程序崩溃.
- */
-
-
- }
- return 0;
- }
复制代码 相关源代码Demo已上传至github:
|
|