黑马程序员技术交流社区

标题: 多态 运行过程的一个提问。麻烦帮分析一下 [打印本页]

作者: 小泉真也    时间: 2014-1-7 23:02
标题: 多态 运行过程的一个提问。麻烦帮分析一下
  1. class Fu
  2. {
  3.         void run1()
  4.         {
  5.                 System.out.println(" fu run_1 ");
  6.         }
  7.        
  8.         void run2()
  9.         {
  10.                 System.out.println("fu run_2");
  11.         }
  12. }

  13. class Zi extends Fu
  14. {
  15.         void run1()
  16.         {
  17.                 System.out.println("zi run_1");        //对父类的run1 方法的重写
  18.         }
  19.        
  20.         void run3()
  21.         {
  22.                 System.out.println("zi run_3");        //子类自己特有的方法
  23.         }
  24. }

  25. public class DuoTaiTest2
  26. {
  27.         public static void main(String[] args)
  28.         {
  29.                 Fu f = new Zi();        //多态,类型提升
  30.                
  31. f.run1();        //        运行结果是 zi run_1
  32. f.run2();        //  运行结果是 zi run_2 【虽然类型提升,但是运行的依然是zi类的?】
  33.                 f.run3();        // 无法编译。
  34.                
  35.         }
  36. }
复制代码
Q【1】Fu f = new Zi();        //把zi类型提升到Fu类应该没错吧

Q【2】可以帮我分析一下吗?  下面的三个,它们分别是怎么调用和执行的?f.run1();        //        运行结果是 zi run_1
f.run2();        // 运行结果是 zi run_2 【虽然类型提升,但是运行的依然是zi类的?】
f.run3();        // 无法编译。



自己看了几遍,有点乱。还没理清过程。有劳各位帮小弟看看

作者: 王新年    时间: 2014-1-7 23:42
创建子类对象后在赋值给父类,属于运行时多态.
此时该对象只能调用父类中方法或子类覆盖父类中的方法,不能调用子类中添加的方法。
当调用那些非父类方法时编译错误所以在Fu f = new Zi(); f.run3();时无法通过编译,
当该对象调用子类和父类中公有的方法时java虚拟机会先查看子类是否覆盖此方法若覆盖则调用子类中的方法若没有覆盖则调用父类中的方法。
所以f.run1();  运行结果是 zi run_1
f.run2(); 运行结果是 zi run_2




求技术分
作者: 松毛    时间: 2014-1-8 08:50
Q【1】:Fu f = new Zi();     是父类引用指向子类对象,没错。Q【2】:f.run1()  //运行结果是:zi run_1  这个没错,因为子类继承了父类,子父类中都有的话,执行子类中的方法。
f.run2();  //你的运行结果是错的吧?你再仔细看一下。这里f调用run2(),而子类中根本就没有run2()这个方法啊,所以它会执行父类中的方法,结果:fu run_2
f.run3();  //创建对象的时候是父类引用指向子类对象,由于父类中没有run3()这个方法,所以编译失败。


在多态中成员函数的特点:
在编译时期(父类引用指向子类对象):参阅引用型变量所属的类中是否有调用的方法,如果有,编译通过,如果没有编译失败。
在运行时期:参阅对象所属的类中是否有调用的方法。
简单总结:成员函数在多态调用时,编译看左边,运行看右边。



作者: 不冬眠的蚂蚁    时间: 2014-1-8 09:35
首先说一下:
f.run1();        //        运行结果是 zi run_1 这个结果你没错
f.run2();        //  运行结果是 zi run_2   这个结果你搞错了 我运行了是fu run_2
----------------------------------------------------------------------------------------------------------
Fu f = new Zi(); 用到了上转型,上转型对象f只能调用子类重写过的方法和父类未被重写的方法(所以有了前两种运行结果),且上转型对象f不能调用子类新定义的成员和方法,所以f对象不能访问子类的新方法run3,它没有权限。所以f.run3无法编译
作者: 小小菜鸟    时间: 2014-1-8 21:19
1】Fu f = new Zi(); ,这个你没有错,确实是把Zi提升了,看左边的是Fu,而你创建出来的是Zi,Zi到Fu确实是一个提升的过程这才是多态的体现形式。
f.run1(); //首先说一下结果。是Zi run -1,这是因为多态有一个覆盖的特性,子类继承父类,如果子类重新把父类继承给它的重新定义,那么子类就覆盖了父类,所以是Zi run-1
f.run2(); //这个结果是fu run-2,你的子类继承父类,但是你的子类有没有重新定义覆盖run2这个方法,所以运行的必然是f run-2 再给你说一下,和run1一样,如果这里子类也重新定义覆盖了父类,那结果就是Zi run-2了
f.run3();//这个结果是无法编译,这里是Zi继承父,就是父类有的全给了子类,但是父类又没有继承子类,就是说,父类的东西,都会给子类,而子类有的却不会给父亲,这里就是Zi具备run3()这个功能,但是Fu只有run1 和run2 根本就没有run3 ,不能无中生有的调用它没有的功能

作者: 花生壳    时间: 2014-1-9 10:12
我比较赞同第一个回答者 ——————》王新年

创建子类对象后在赋值给父类,属于运行时多态.
此时该对象只能调用父类中方法或子类覆盖父类中的方法,不能调用子类中添加的方法。

所以f.run1();  运行结果是 zi run_1
f.run2(); 运行结果是 zi run_2  ×

      f.run2();运行结果是fu run_2

作者: daoyua    时间: 2014-1-9 10:14
其实我有个最大的疑问,我看了你的代码,你就没写输出zi_run2的语句,怎么会打印出来呢,你上传的代码不全




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2