黑马程序员技术交流社区

标题: 多态的问题 [打印本页]

作者: 章闽    时间: 2012-10-22 11:20
标题: 多态的问题

class A
{
public void f()
{
System.out.printf("AAAA\n");
}
}

class B extends A
{
public void f()
{
System.out.printf("BBBB\n");
}
}

public class TestPoly
{
public static void main(String[] args)
{
A aa = new A();
B bb = new B();

aa.f();
bb.f();

aa = bb;
aa.f();
}
}

根据Java多态的一个定义:通过父类引用只能访问子类对象从父类继承过来的成员
类B中重写的了A中的方法f();这个应该是B类中的一个方法了 但是aa = bb;aa.f();输出的结果是bb.f();中的结果啊 这里不是跟上面有矛盾吗?


作者: 陆建平    时间: 2012-10-22 11:26
你是吧aa提升了,是他具备了B类的功能
作者: 张其辉    时间: 2012-10-22 12:40
这个不矛盾,aa = bb;相当于A aa= new B();向上转型了。
因为你的子类和父类中都有f()方法,对于非静态方法:在编译时参考引用型变量所属类中(就是父类中)是否具有调用的f()方法,有,编译通过。
但是在运行时,参考的是对像所属类中是否具有调用的方法,就是子类中了,有的话运行子类的,子类中没有就往父类中寻找,有运行父类的,父类也没有就运行失败。
作者: 张飞年    时间: 2012-10-22 12:53
通过父类引用只能访问子类对象从父类继承过来的成员--- 应该这样理解吧:子类对象赋给父类引用时,父类引用只能访问子类对象从父类继承过来的成员(包括在子类中已重写的)。记住一点,继承是类之间的关系,重写是方法之间的关系。你的例子我少加了点东西,就好理解了;
=================================================================
  1. class A {
  2.         public void f() {        //它其实没有被继承过去,因为子类直接重写了它
  3.                 System.out.printf("AAAA\n");
  4.         }
  5.         public void fun(){        //它会被子类整个继承,并且子类没有重写它
  6.                 System.out.println("fun run...");
  7.         }
  8. }

  9. class B extends A {
  10.         public void f() {        //重写过的f方法
  11.                 System.out.printf("BBBB\n");
  12.         }
  13.         public void fun1(){        //子类特有的方法
  14.                 System.out.println("我能编译,不能运行");
  15.         }
  16. }

  17. public class TestPoly {
  18.         public static void main(String[] args) {
  19.                 A bb = new B();        //子类对象给父类引用
  20.                 bb.f();        //多态就是编译时方法看父类有没有,运行时看实际对象类有没有,这里运行的是子类的f()
  21.                 bb.fun();        //这里运行的也是子类的fun(),只不过是直接从父类中继承过来的罢了
  22.                 bb.fun1();        //能编译不能运行,因为父类中没有fun1

  23.                 A aa = bb;        //这个就是换个手,a类引用给a类引用(运行时仍参照b对象)
  24.                 aa.f();
  25.         }
  26. }
复制代码

作者: 孙岳    时间: 2012-10-22 13:40
aa.f() 相当于 new A().f()  ,调用A中的f()
bb.f() 相当于 new B().f()  ,调用B中的f()
aa=bb 之后,
aa.f() 相当于 bb.f()  也就是 new B().f()
所以调用的还是B中的f()
作者: 任雷彬    时间: 2012-10-22 14:30
首先这两者是不矛盾的。
代码中:

A aa = new A();  //创建父类对象
B bb = new B();  //创建子类对象

aa = bb;  只是传递的是对象引用,并不会进行类型自动提升。
只是两者会指向在堆内存中的相同地址。
所以对象 aa.f();调用父类的方法, bb.f(); 调用子类的方法。
虽然子类复写父类的方法,但是子类对象调用本类方法。

而  A aa = bb;
bb会自动提升为父类 A; 则  aa.f(); 输出的结果是aa.f();而不是bb.f();


作者: 黑马吕世成    时间: 2012-10-22 16:16
本帖最后由 NESUN 于 2012-10-22 16:19 编辑

    这里的aa = bb发生了向上的类型转换,其实就是bb对象换了一个马甲而已,看着是aa,最后运算的时候还得自己来。所以就不难解释,为什么会出现调用的是aa.f(),结果却是调用了bb.f()方法。
  还有一点就是方法重写之后是自己的方法吧?应该不是继承了吧?我是这么觉得的,你怎么看呢!




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