黑马程序员技术交流社区

标题: 一个继承问题 [打印本页]

作者: 刘乃宽    时间: 2013-7-25 21:51
标题: 一个继承问题
  1. class A {

  2.   void fun1() {

  3.     System.out.println(fun2());

  4.   }

  5.   int fun2() {

  6.     return 123;

  7.   }

  8. }


  9. class B extends A {

  10.   int fun2() {

  11.     return 456;

  12.   }

  13.   public static void main(String argv[]) {

  14.     A a;

  15.     B b = new B();

  16.         b.fun1();

  17.     a = b;

  18.         a.fun1();

  19.   }

  20. }
复制代码
父类中的方法,子类在继承的时候在复制一份这个方法吗?也就是说子类和父类各自都有两个相同的方法
我的理解对吗?只有一个方法,这个方法是this在控制。还有父类被重写的方法和原父类的方法在加进内存的时候是怎么存在的?
作者: Mr_Free    时间: 2013-7-25 23:06
不是这样的,子类继承父类,子类能用父类的方法。父类被继承,他只能用他自己有的方法,不能使用子类的方法。
我给你说一下子类的实例化过程。
子类的所有的构造函数,默认都会访问父类中的空参数构造函数。当父类中没有空参数的构造函数,子类必须手动通过super或者this语句形式来指定要访问的构造函数。
子类类名(){//子类的构造函数系统也是默认会加的
super();//如果你不写系统默认会加的
}
为什么要访问父类的构造函数?因为父类中的数据子类可以直接获取,所以子类对象在建立时,需要先看父类是如何对这些数据进行初始化的。

这里就回答了你的第二个问题,子类对象初始化之后,先访问父类的方法,然后在调用自己的方法,如果2个方法名,参数列表都相同,那在调用的时候就执行子类的方法。这叫做覆盖。就相当于    String s="xxxx";这个是父类的变量值,然后子类也有一个String s="YYYY";那么系统在调用s的时候,他的取值肯定是s="YYYY";一样的道理 。


作者: dicegame    时间: 2013-7-25 23:23
要看父类中方法名前面的权限修饰符,
这个例子中,父类B的fun1()方法没有权限修饰符(即缺省或默认),子类B可以继承,
此时B中有两个方法,从A中继承的fun1()和自己重写了的fun2(),
因此语句b.fun1();会输出456,
由于子类对象可以看做父类对象,因此可以使父类变量指向子类对象,即用子类变量给父类变量赋值
语句a = b 正是使父类变量a指向堆内存中子类B的对象
因此a.fun1()还是会调用B中的fun2()方法,因此也会输出456
程序的运行结果就是:
456
456
语句a = b是对象多态性的体现,虽然a是A的变量,但实际却指向B的对象,因此a.方法都是调用B中的方法
这是关键。
这个例子中假如在class A中把fun1()定义成private void fun1()
则eclipse会classB的b.fun1()和a.fun1()报错,都提示类型A中的方法不可见
可见当父类的方法前有private修饰时,子类是不可见的,更谈不上继承
作者: litaojisuanji    时间: 2013-7-26 00:15
子类继承父类时,拥有父类的一切方法和变量(除了私有的),如果子类有父类同名同参的方法,子类将会覆盖父类的方法。
B b = new B(); 声明一个b对象,B已经继承A,并重写fun2方法,
此时B的fun2方法已经变成返回456了,这时运行b,fun1();fun1()打印fun2,打印出来456;
A a = b; 把b对象赋值给a,引用型变量是a,但方法还是b,所以打印出来还是456。
作者: 黑马王晓明    时间: 2013-7-26 01:19
继承的目的就是重用父类的代码和数据,而不需要子类从头写起  默认会调用父类的构造方法
子类继承了父类 会继承父类的成员变量和成员方法 但是不能继承父类的构造方法
子类继承了父类的fun1() 和 fun2()方法 并重写(覆盖)了fun2()方法
创建子类的对象 调用fun1() 是调用的自己的方法 而fun1()又会调用子类重写父类的fun2()方法 结果是 456
然后又把子类对象b的值赋给了父类的引用变量a 父类的引用指向了子类的对象 这是向上转型
因此a.fun1()其实还是调用子类中的fun2()方法,因此结果也是 456


作者: xwf4348    时间: 2013-7-26 07:42
这个例子中,父类B的fun1()方法没有权限修饰符(即缺省或默认),子类B可以继承,
此时B中有两个方法,从A中继承的fun1()和自己重写了的fun2(),
因此语句b.fun1();会输出456,
由于子类对象可以看做父类对象,因此可以使父类变量指向子类对象,即用子类变量给父类变量赋值
语句a = b 正是使父类变量a指向堆内存中子类B的对象。也就是多态的体现。
因此a.fun1()还是会调用B中的fun2()方法,因此也会输出456
程序的运行结果就是:
456
456





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