黑马程序员技术交流社区

标题: 昨天看到一个关于继承的帖子,突然产生了一个有意思的... [打印本页]

作者: 李阳    时间: 2013-1-22 13:46
标题: 昨天看到一个关于继承的帖子,突然产生了一个有意思的...
本帖最后由 李阳 于 2013-1-22 19:26 编辑

昨天看到的问题如下:
class A
{
   A()
  {
   fun();
  }
  void fun()
   {}
}
class B extends A
{
   B(){}
  void  fun()
   {}
}
代码大概是这个样子。建立子类对象时,调用子类的的构造函数,先执行父类的构造函数。因为父类的fun()函数被子类重写了,所以调用的是子类的fun()函数。那么问题来了,如下面的代码:
class ExtendsDemo3
{
        public static void main(String[] args)
        {
                Person1 p1 = new Person1();
                System.out.println(p1.guoji+"---"+p1.huji);
        }
}
class Person
{
         String guoji;//国籍
        Person()
        {
                fun1();//this.guoji = guoji;偏不这样写
        }
        void fun1()
        {
                guoji = "china";
        }
}
class Person1 extends Person
{
    String huji;//户籍
        Person1()
        {
        }
        void fun1()
        {
                huji = "x省x市x县x乡";
        }
}
问题产生了:父类初始化时guoji=china,但是子类初始化时guiji=null;也就是说子类没拿到父类的初始化。
这算不算一个BUG?纠结死了,求解答。
补充:子类初始化之前先父类初始化,就是为了让子类知道父类是如何对数据操作的。第二个例子中,子类并不知道父类如何初始化的,那么干嘛还要初始化父类呢?
这不就很矛盾吗?
作者: 张洪慊    时间: 2013-1-22 14:28
本帖最后由 张洪慊 于 2013-1-22 14:30 编辑

Person1 p1 = new Person1();
-->调用子类构造函数Person(){}
--->调用父类构造函数
         Person()
        {
                fun1();
        }
     此时,fun1()调用的为子类的fun1()-->huji = "x省x市x县x乡";
     (子类fun1()复写了父类fun1())
   String guoji;//从父类继承 还没有被初始化,为null
不知道说的什么BUG?
作者: 王溢君    时间: 2013-1-22 14:32
正如你所说的一样。因为父类的fun1()函数被子类重写了,所以调用的是子类的fun1()函数。当new一个p1时,调用父类构造函数,里面是fun1方法,注意这个方法被子类复写了,所以执行的是子类的去了!
  void fun1()
        {
                huji = "x省x市x县x乡";
        }
所以guiji并没有赋值!
作者: 陈丽莉    时间: 2013-1-22 14:44
      的确,Person类对象单独初始化时,guoji=“china”;但题中是创建子类对象从而执行的父类的构造函数,因为子类Person1覆写了父类的fun1()方法,也就是说,子类选择了独有的对guoji和huji 的初始化,是子类自己改变了父类的赋值方法,既然那么写了,明显就是不要guoji的初始化,所以并不算是bug。
    如果想既实现guoji的赋值,又实现huji的赋值,又何必要覆写呢,子类的赋值方法换一个名字,在构造函数中调用就好了~
作者: 陈丽莉    时间: 2013-1-22 14:45
本帖最后由 陈丽莉 于 2013-1-22 14:49 编辑

比如:
class ExtendsDemo3
{
        public static void main(String[] args)
        {
                Person1 p1 = new Person1();
                System.out.println(p1.guoji+"---"+p1.huji);
        }
}
class Person
{
         String guoji; //国籍
        Person()
        {
                fun1(); //this.guoji = guoji;偏不这样写
        }
        void fun1()
        {
                guoji = "china";
        }
}
class Person1 extends Person
{
    String huji; //户籍
        Person1()
        {
                fun2();                                     //子类构造函数调用重新命名的方法
        }
        void fun2()
        {
                huji = "x省x市x县x乡";            //改了名字,不要覆写
        }
}




QQ截图20130122144845.png (5.42 KB, 下载次数: 29)

QQ截图20130122144845.png

作者: 贾文泽    时间: 2013-1-22 14:47
这不是bug额,,
目测 是因为你的子类对父类的fun1方法覆盖了,所以你的这句 fun1();//this.guoji = guoji;偏不这样写   
fun1应该调用的是子类的fun1.。。。

作者: 李阳    时间: 2013-1-22 18:42
子类初始化之前父类初始化,就是为了让子类知道父类是如何对数据操作的。第二个例子中,子类并不知道父类如何初始化的,那么干嘛还要初始化父类呢?
这不就很矛盾吗?
作者: txl    时间: 2013-1-22 19:20
本帖最后由 黑马唐贤来 于 2013-1-22 19:23 编辑

楼主, Person1 既然继承了 Person类,就不应该再去覆盖 fun1()方法,而是需要将Person中的fun1()修改为私有,Person1中的fun1()也私有,这样就不冲突了
  1. class ExtendsDemo3
  2. {
  3.         public static void main(String[] args)
  4.         {
  5.                 Person1 p1 = new Person1();
  6.                 System.out.println(p1.guoji+"---"+p1.huji);
  7.         }
  8. }
  9. class Person
  10. {
  11.          String guoji;//国籍
  12.         Person()
  13.         {
  14.                 fun1();//this.guoji = guoji;偏不这样写
  15.         }
  16.         private void fun1()    //此处私有,因为子类继承无意义

  17.         {
  18.                 guoji = "china";
  19.         }
  20. }
  21. class Person1 extends Person
  22. {
  23.                 String huji;//户籍
  24.         Person1()
  25.         {
  26.                 fun1();
  27.         }
  28.         private void fun1()       //此处应该私有
  29.         {
  30.                 huji = "x省x市x县x乡";
  31.         }
  32. }
复制代码

作者: 刘军亭    时间: 2013-1-22 19:21
李阳 发表于 2013-1-22 18:42
子类初始化之前父类初始化,就是为了让子类知道父类是如何对数据操作的。第二个例子中,子类并不知道父类如 ...

子类当然知道父类如何初始化的。调用父类的构造函数就是去初始化父类了,但是子类重写了fun1()方法,显然是不想运行父类的fun1()方法,而是运行自己的fun1()方法。




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