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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 HM张博文 于 2013-6-7 21:42 编辑

  1. <P>class 毕姥爷
  2. {
  3. void 讲课()
  4. {
  5. System.out.println("管理");
  6. }
  7. void 钓鱼()
  8. {
  9. System.out.println("钓鱼");
  10. }
  11. }

  12. class 毕老师 extends 毕姥爷
  13. {
  14. void 讲课()
  15. {
  16. System.out.println("Java");
  17. }
  18. void 看电影()
  19. {
  20. System.out.println("看电影");
  21. }
  22. }


  23. class DuoTaiDemo2
  24. {
  25. public static void main(String[] args)
  26. {
  27. // 毕老师 x = new 毕老师();
  28. // x.讲课();
  29. // x.看电影();

  30. 毕姥爷 x = new 毕老师();
  31. x.讲课();
  32. x.钓鱼();

  33. 毕老师 y = (毕老师)x;//ClassCastException
  34. y.看电影();




  35. }
  36. }</P>
  37. <P>//按向下转型的方法,打印出来的最后是讲课是(毕老师的)Java,说明两个方法相同时,取的是子类的方法</P>
复制代码
  1. class Fu
  2. {
  3. int num = 3;

  4. }


  5. class Zi extends Fu
  6. {
  7. int num = 4;

  8. }



  9. class DuoTaiDemo3
  10. {
  11. public static void main(String[] args)
  12. {

  13. Fu f = new Zi();//
  14. System.out.println(f.num);


  15. }
  16. }
复制代码
而下面的这个程序打印出来却是3,说明向下转型时,父类和子类成员相同时,打印出来的是父类的
结果为什么会有差异呢?


1.jpg (5.52 KB, 下载次数: 0)

1.jpg

2.jpg (4.44 KB, 下载次数: 0)

2.jpg

评分

参与人数 1技术分 +1 收起 理由
Sword + 1

查看全部评分

3 个回复

倒序浏览
因为在多态中,成员变量和成员函数,静态和非静态是有区别的.我给你归纳一下(我的笔记,直接剪切过来了,稍微再括号里加了点注释)
Fu f=new Zi();
|-- 非静态成员变量的特点
    编译时期特点
    |-- 引用型变量所在的类中(即父类),没定义这个变量编译失败(父类中没有这个变量,不管子类有没有都会编译失败,因为你这时候是相当于父,父不能用子的属性)
    |-- 引用型变量所在的类中,定义了这个变量编译成功
    运行时期特点
    |--  运行时期,参考引用型变量所属的类中的结果(所以你输出的是父类中的3而不是子类中的4)
  |-- 非静态成员方法的特点
    编译时期特点
    |-- 编译时期,参考引用型变量所在的类中,有没有定义这个方法,有编译成功,没有编译失败(父类必须有这个类)
    运行时期特点
    |-- 运行时期,虚拟机动态的绑定到了子类对象中,运行的是子类中重写的方法(这句还算好懂)
  |-- 静态成员变量特点
   编译时期特点
   |-- 参考引用型变量所在的类中,是否定义了静态变量,定义了编译成功,没定义编译失败
   运行时期特点
   |-- 参考引用型变量所以在类中的结果
  |-- 静态成员方法特点
   编译时期特点
   |-- 参考引用型变量所在类中,是否定义了这个静态方法,没有定义编译失败,定义了就编译成功
   运行时期特点
   }-- 参考引用型变量所在类中的静态方法

  总结:
   成员变量
     |-- 不论是静态成员变量还是非静态成员变量
         编译时期参考等号左边
  运行时期参考等号左边
   成员方法
     |-- 静态成员方法
         编译时期参考等号左边
  运行时期参考等号左边
     |-- 非静态成员方法
         编译时期参考等号左边
  运行时期参考等号右边   虚拟机将动态绑定到子类对象中


这么多晕了吧??其实上面的没必要太过较真的去理解,这里只需要简单的记住下面的话就好
非静态成员方法,编译看左边,运行看右边
                 其他情况,编译运行都看左边

多态的理解,我把我以前在不加分区域帖子上的内容给你复制过来吧

  1. <P> </P>
复制代码

  1. class KD//孔子爹()
  2. {
  3. int age=55;//年龄属性;
  4. void teach()//讲课功能(){讲做官}
  5. {
  6. System.out.println("怎么做官");
  7. }
  8. }
  9. class K extends KD//孔子 继承 孔子爹
  10. {
  11. int age=33;//年龄属性;
  12. void teach()//讲课功能(){讲论语}
  13. {
  14. System.out.println("学论语");
  15. }
  16. void play()
  17. {
  18. System.out.println("玩象棋");
  19. }
  20. }
复制代码
一个人来孔子家来找孔子爹,但孔子爹不在,这时要只能孔子去办成孔子爹
KD k=new K()
//孔子化妆成孔子爹,孔子提升为孔子爹,自动转向转型
k.teach()
//调用孔子爹的讲课功能,但是孔子已经将这个功能覆盖了,只能讲论语了
System.out.println(k.age);
//此时打印的为55,因为如果你打印33,孔子就穿帮了……嗯,就这样记吧……
//这时,孔子的朋友来找孔子,却碰到了化妆成孔子爹的孔子,所以此时,孔子会还原,卸妆
K kk=(K)k;
//将以提升为孔子爹的孔子向下转型为孔子,强制类型转换。
//格式:目标类型 变量名=(目标类型))提升为父类类型的引用
kk.play();
//此时相当于纯子类对象的引用。


差不多明白就好了,以后用的多了就懂了

点评

thank you  发表于 2013-6-5 22:42

评分

参与人数 1技术分 +1 收起 理由
Sword + 1

查看全部评分

回复 使用道具 举报
楼主:
1、你的代码,让我很不适应,或许是你粘贴的时候出问题了吧。
2、我对于多态的理解
    对于成员函数:
        不向下转型时,只能调用父类中定义的成员函数,不能调用子类特有的成员函数;
        向下转型,此时可以调用子类特有的成员函数
    对于成员变量:
        系统调用时会先查看父类中是否有这个成员变量,有的话就调用。
        虽然你的子父类中都定义了num,但打印的父类的num。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马