A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 叶子哥 中级黑马   /  2016-5-19 10:30  /  840 人查看  /  2 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文


  1. /**
  2. *  1.多态的理解
  3.         多态本是指事物的多种形态.(例如:水可以为液态水,固态冰,气态水蒸气)
  4.         代码中的体现为:父类的指针 指向了 子类的对象.

  5.     2.OC中多态的实现,前提是:
  6.         (1)类与类之间有继承关系.
  7.         (2)子类中有对父类中的方法进行了重写.

  8.     3.多态的好处:
  9.         如果函数或方法中的参数使用的是父类类型,则可以传入父类或者子类的对象,而不用定义多个函数或方法来匹配相应的类.

  10.     4.多态的局限性:
  11.         父类类型的变量不能直接调用子类中特有的方法.如果必须要调用,则必须先强制转换成子类,然后再近些调用.

  12. 说了这么多了,接下来进行具体的测试:
  13. 思路:
  14.     创建两个类(人类 和 学生类),具有继承关系,并且学生类新增了特有的属性和方法,并对人类中的一个方法进行了重写.
  15. 请先往下看,不着急看结论.


  16. 总结:
  17.     (1)OC语言是一门弱语法语言,在创建对象时,编译器在编译时并不能检测真实类型,只能在运行时才能动态检测对象类型.
  18.     (2)使用多态需要十分注意类与类之间的关系,子类本身所拥有的属性和方法就比父类多,并且子类拥有父类的所有属性和方法(包括重写的方法).
  19.     (3)不同类之间的对象转换问题:本质上不是真正的一个对象转变成另一个对象(逻辑上或情理上也是不可能的).这样的转换只是告诉编译器我们进行
  20.     了类型的转换,实际上指针所指向的那块内存空间一直都没有变化.
  21.         第一种情况:当把子类对象强制转换成父类对象时,只是把子类对象所拥有的特有属性和方法暂时屏蔽了.一旦把转换成的父类对象,再次转换成子  
  22.     类对象时又可以访问子类对象所拥有的特有属性和方法.
  23.         第二种情况:当把父类对象强制转换成子类对象时,其实我们是对编译器进行欺骗操作.让编译器误认为转换成的子类对象,真的是一个子类对象,本
  24.     质上它还是个父类对象.所以编译时不会报错,一旦执行子类对象所拥有的特有属性和方法时,就会造成程序的崩溃.
  25. */

  26. #import <Foundation/Foundation.h>
  27. #import "YYPerson.h"
  28. #import "YYStudent.h"

  29. int main(int argc, const char * argv[]) {
  30.     @autoreleasepool {
  31.         
  32.         //1.直接创建一个父类对象
  33.         YYPerson *p1 = [YYPerson new];
  34.         [p1 eat];
  35.         [p1 sleep];
  36. //        [p1 study];  //父类对象不能调用子类中的方法
  37.         
  38.         //2.直接创建一个子类对象
  39.         YYStudent *stu1 = [YYStudent new];
  40.         [stu1 eat];    //子类对象可以直接调用父类中的对象方法
  41.         [stu1 sleep];  //子类对象可以直接调用父类中的对象方法
  42.         [stu1 study];
  43.         
  44.         //3.多态的实现
  45.         YYPerson *p2 = [YYStudent new];  //此时:父类的指针指向了子类的对象
  46.         [p2 eat];      //结果p2调用的是学生类中的 eat方法.
  47.         [p2 sleep];    //由于没有方法的重写,p2调用的仍然是人类中的 sleep方法
  48. //        [p2 study];  //父类类型的变量不能直接调用子类中特有的方法,不能通过编译.
  49.         
  50.         YYStudent *stu2 = (YYStudent *)p2;  //把父类的对象强制转换成子类的对象
  51.         [stu2 study];                       //此时能调用子类中特有的方法  study方法
  52.         
  53.         //4.子类对象 强制转换成 父类对象
  54.         YYStudent *stu3 = [YYStudent studentWithName:@"杰克" andAge:18 andNumber:@"5201314" andScore:100];
  55.         YYPerson *p3 = (YYPerson *)stu3;
  56.         [p3 eat];         //调用是学生中 eat方法
  57.         [p3 sleep];       //调用的是人类中的  sleep方法
  58. //        [p3 study];     //不能调用 --编译器直接报错
  59.         NSLog(@"stu3 address = %p",stu3);  //stu3 address = 0x1005006a0
  60.         NSLog(@"p3   address = %p",p3);    //p3   address = 0x1005006a0
  61.         /**
  62.          *  结论:OC中可以把子类对象强制转换成父类对象,其实这两个指针 指向了同一地址.并且转换成父类对象后,不能再调用子类中特有的属性和方法.
  63.          */
  64.         
  65.         
  66.         //5.父类对象 强制转换成 子类对象
  67.         YYPerson *p4 = [YYPerson personWithName:@"汤姆" andAge:32];
  68.         YYStudent *stu4 = (YYStudent *)p4;
  69.         [stu4 eat];     //调用的是人类中的  eat方法
  70.         [stu4 sleep];   //调用的是人类中的  sleep方法
  71. //        [stu4 study];   //编译器不会报错,但是在执行时会崩溃,会告诉找不到 study方法.
  72.         /**
  73.          *  结论:OC中不可以把父类对象强制转换成子类对象,对编译器进行了欺骗操作,一旦访问了子类中特有的属性或者方法,就会导致程序崩溃.
  74.          */
  75.         
  76.         
  77.     }
  78.     return 0;
  79. }
复制代码
相关源代码Demo已上传至github:
游客,如果您要查看本帖隐藏内容请回复

2 个回复

倒序浏览
好详细,收下了,呵呵
回复 使用道具 举报
okok啦!这个好东东啦!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马