使用重写方法在java中继承

时间:2016-03-18 13:51:09

标签: java inheritance

我在java中进行了关于继承的练习:

public class Gran {
  private int x;
  public Gran() {
    this.x = 68; 
  }
  public int age() {
    this.x = this.x+1; return this.x; 
  }
  @Override
  public String toString() {
    return "Gran " + age();
  }
}

public class Dad extends Gran {
  private int x;
  public Dad(){
    this.x = 41; 
  }
  @Override
  public String toString() {
    return "Dad " + age();
  }
}

public class Sis extends Dad {
  private int x;
  public Sis() {
    this.x = 17;
  }
  @Override
  public int age() {
    System.out.print("Sis ");
    return super.age() - x;
  }
  @Override
  public String toString() {
    return "Sis " + super.toString();
  }
}

所以当我实施时:

Gran[] family = new Gran[] { new Gran(), new Dad(), new Bro(), new Sis() };

for (Gran member : family) {
    System.out.println(member.toString());
}

显示成员Sis : Sis Sis Dad 52

有人可以解释原因吗?

所以这就是我所想的,当调用Sis.toString()方法时,这意味着:

  • return "Sis" + super.toString()
  • super.toString() = Dad.toString() = return "Dad" + age()

我很困惑为什么此时age()方法来自Sis,而不是来自Gran Gran ..

我感谢任何帮助..

2 个答案:

答案 0 :(得分:5)

Dad' toString()调用age()时,应调用的实际方法取决于调用它的对象的运行时类型。由于该对象是Sis的一个实例,因此调用了age() Sis方法,该方法也会调用Gran' s age(),因为它包含super.age()致电return "Sis" + super.toString()

所以,我们有:

super.toString() 

,其中

"Dad " + age()

返回

age()

但在它返回之前"爸爸52" (69 - 17返回age()),Sis Sis Dad 52 打印另一个" Sis"

所以最终输出是

$builder->add('home_team', 'choice', [$options])
    ->add('away_team', 'choice', [$more_options])
    ->add('timestamp', 'datetime_picker', [$usual_stuff]);

答案 1 :(得分:1)

你得到了输出:

  

Sis Sis Dad 52

由于: 1)当您致电new Sis()时,会调用Sis构造函数,设置x=17

2)然后你调用Sis.toString()方法。

3)Sis.toString()来电super.toString()

4)super =爸爸,Dad.toString()返回:"Dad" + age(),调用年龄方法。

这是我认为你感到困惑的地方。你期望它可以调用爸爸的年龄方法,因为你是在爸爸的toString()方法。但是,您使用的实例是Sis类型。因此,当您致电age()时,会调用Sis.age()方法(因为您已经超载了Dad.age()

5)调用Sis.age()方法,打印“Sis”,然后调用super.age() - x;

这是真正丑陋的地方。因为你已经在每个父类和子类中定义了变量x你正在经历擦除(不是一个好习惯),其中孩子的x版本会删除父x的可见性和在尝试理解我们引用或修改的x时会产生混淆。

以下是调用Sis.toString()时age / x会发生什么:

1)在Sis.toString()中,super.toString()被调用。

2)super.toString() = Dad.toString()。在Dad.toString()中调用age()方法。

3)因为我们是Sis类型,Sis.age()方法将被执行。

4)Sis.age()调用super.age(),然后减去x的值。

5)在super.age()上调用Dad。不用等了! Dad未覆盖age(),因此爸爸的父亲 - Gran.age()被调用。

6)此时在Gran.age()中,Gran.x的值为68.在Gran.age()中,它会增加x的值,使其为69,并返回值。< / p>

7)因此,Gran.age将值69返回Sis.age()Sis.x的值仍为17.请记住,Sis和Gran都定义了自己的x

8)最后,Sis.age()方法在减去Gran.age()(17)= 52的值后返回Sis.x调用的结果(69)。

不太漂亮。我认为这清楚地突出了擦除的负面影响,并在父类和子类中定义了相同的变量x - 只是不要这样做

相反,将Gran中的x定义为私有,并提供公共或受保护的getX()(更好地称为'age')方法以授予对子类的访问权限。这样可以避免这种意外行为。