使用重写方法在构造函数链执行期间调用哪个方法?鉴于以下两个类,我需要知道在创建MountainBike对象时将调用哪个setGear方法。我真正的项目与自行车无关,我试图覆盖一个类来改变在超类的构造函数中调用的一个方法的行为,我不知道它应该如何工作......
public class Bicycle {
public int cadence;
public int gear;
public int speed;
public Bicycle(int startCadence,
int startSpeed,
int startGear) {
setGear(startGear);
setCadence(startCadence);
setSpeed(startSpeed);
}
public void setCadence(int newValue) {
cadence = newValue;
}
public void setGear(int newValue) {
gear = newValue;
}
public void applyBrake(int decrement) {
speed -= decrement;
}
public void speedUp(int increment) {
speed += increment;
}
}
public class MountainBike extends Bicycle {
public int seatHeight;
public MountainBike(int startHeight,
int startCadence,
int startSpeed,
int startGear) {
super(startCadence, startSpeed, startGear);
seatHeight = startHeight;
}
public void setHeight(int newValue) {
seatHeight = newValue;
}
public void setGear(int newValue) {
if(newValue<4)
gear = newValue;
else{
gear = 4;
}
}
}
答案 0 :(得分:1)
如果你调用它,子类的方法将执行。但是,它目前尚未被调用。
答案 1 :(得分:1)
这里有一些很好的答案,但我想提一下你应该考虑使用构图。我已经看到许多项目,其中继承被用于可以以更好的方式完成组合的功能。在以后的项目阶段,这可能会导致严重的问题和代码气味。
请参阅“赞成合成而不是继承”:Effective Java: Item 16
答案 2 :(得分:1)
正如其他人所指出的,它是被调用的子类'setGear。
但是,我想提一下,在构造函数中调用重写方法是危险的,并且不赞成,尤其是如果这些方法依赖于子类的字段。例如,如果MountainBike有一个字段,maxGear和setGear引用它(而不是一个魔术常量4)。问题是你的MountainBike构造函数看起来像:
public MountainBike(args...) {
super(args); // must come first!!!
maxGear = 4;
}
当Bicycle构造函数调用setGear()时,它将调用MountainBike的setGear,但是maxGear尚未设置 - 它将为0。
答案 3 :(得分:0)
如果你实例化覆盖类,那么它的重写方法将是执行的方法。
Bicycle bike;
bike = new Bicycle(1,2,3);
bike.setGear(8);//Bicycle's setGear is run
bike = new MountainBike(1,2,3,4);
bike.setGear(8);//MountainBike's setGear is run
- 修改:反映OP编辑的问题(setGear
现在从Bicycle
的构造函数中调用) -
Bicycle b=new MountainBike(1,2,3,4);
鉴于您实例化了MountainBike
,MountainBike
的{{1}}被执行了。
答案 4 :(得分:0)
更一般地说,你不应该让对象引用转义它的构造函数,无论是通过将“this”作为参数传递给另一个类的方法,还是通过调用可以被覆盖的方法。
即使可以,也不应该从超类构造函数中调用重写方法。原因是超类的构造函数在子类之前运行,并且对象状态可能不一致。例如,子类中的最终字段尚未设置。
答案 5 :(得分:-1)
是的,重写基类方法以在派生类中创建和容纳新功能是定义子类型 - 多态特征的原因。
class A{methodA...}
class B extends A{methodA...}
A a=new B;
a.methodA(); <<<< this should call B's methodA