-2

在构造函数链执行期间使用覆盖方法调用哪个方法?鉴于以下两个类,我需要知道在创建 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;
        }

    }    
}
4

6 回答 6

1

正如其他人所指出的,它是子类的 setGear 被调用。

但是,我想提一下,在构造函数中调用被覆盖的方法是危险的并且不受欢迎,尤其是当这些方法依赖于子类的字段时。例如,如果 MountainBike 有一个字段,maxGear 和 setGear 引用它(而不是魔术常数 4)。问题是您的 MountainBike 构造函数看起来像:

public MountainBike(args...) {
  super(args);  // must come first!!!
  maxGear = 4;
}

当 Bicycle 构造函数调用 setGear() 时,它将调用 MountainBike 的 setGear,但 maxGear 尚未设置- 它将为 0。

于 2012-01-28T01:30:27.020 回答
1

如果调用它,子类的方法将执行。但是,它目前没有被调用。

于 2012-01-28T00:49:36.290 回答
1

这里有一些很好的答案,但我想提一下,你应该考虑改用组合。我见过许多项目,其中继承被用于可以以更好的方式通过组合完成的功能。在项目的后期阶段,这可能会导致严重的问题和代码异味。

请参阅“优先组合优于继承”:Effective Java: Item 16

于 2012-01-28T01:01:27.123 回答
0

更一般地说,您不应该让对象引用逃脱它的构造函数,无论是通过将“this”作为参数传递给另一个类的方法,还是通过调用可以覆盖的方法。

即使可以,也不应该从超类构造函数中调用被覆盖的方法。原因是超类的构造函数在子类之前运行,对象状态可能不一致。例如,子类中的最终字段尚未设置。

于 2012-01-28T08:26:16.763 回答
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);

鉴于您实例化 a MountainBike, MountainBike'setGear被执行。

于 2012-01-28T00:50:32.187 回答
-1

是的,重写基类方法以在派生类中创建和容纳新功能是定义子类型 - 多态特性的原因。

class A{methodA...}
class B extends A{methodA...}
A a=new B;
a.methodA(); <<<< this should call B's methodA
于 2012-01-28T00:55:36.083 回答