在构造函数链执行期间使用重写方法调用哪个方法

发布于 2024-12-29 13:42:03 字数 1341 浏览 4 评论 0原文

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

    }    
}

Which method is called during Constructor chain execution with an overriding method? Given the following two classes I need to know which setGear method would be called when creating a MountainBike object. My real project has nothing to do with bicycles, I am trying to override a class to change the behavior of one method that is called in the constructor of the super class and I'm not sure how it should work...

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;
        }

    }    
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

唯憾梦倾城 2025-01-05 13:42:03

如果调用它,子类的方法将执行。但是,目前尚未调用它。

If you call it, the subclass's method will execute. However, it's not currently being called.

云淡风轻 2025-01-05 13:42:03

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

请参阅“优先考虑组合而不是继承”:有效的 Java:第 16 项

There are some good answers here yet, but I would like to mention that you should consider to use composition instead. I have seen many projects where inheritance was used for features which could have done with composition in a much better way. In later project stages, this can lead to serious problems and code smells.

See "Favor composition over inheritance": Effective Java: Item 16

凉城 2025-01-05 13:42:03

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

但是,我想提一下,在构造函数中调用重写的方法是危险的并且令人不悦,特别是如果这些方法依赖于子类的字段。例如,如果 MountainBike 有一个字段,则 maxGear 和 setGear 会引用它(而不是魔法常量 4)。问题是你的 MountainBike 构造函数看起来像这样:

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

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

As other's have noted, it is the subclass' setGear that gets called.

However, I wanted to mention that calling overridden methods in a constructor is dangerous and frowned upon, especially if those methods rely upon fields of the subclass. For example, if MountainBike had a field, maxGear, and setGear referred to it (instead of a magic constant 4). The problem is that your MountainBike constructor looks something like:

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

When the Bicycle constructor calls setGear(), it will call MountainBike's setGear, but maxGear has not yet been set - it will be 0.

三生池水覆流年 2025-01-05 13:42:03

如果实例化重写类,则将执行其重写方法。

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编辑的问题(现在从Bicycle的构造函数中调用setGear)--

Bicycle b=new MountainBike(1,2,3,4);

假设您实例化了一个< code>MountainBike,MountainBikesetGear 被执行。

If you instantiate the overriding class, then its overriding methods will be the ones executed.

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

-- Edit: to reflect OP edited question (setGear is now called from within Bicycle's constructor) --

Bicycle b=new MountainBike(1,2,3,4);

Given that you instantiate a MountainBike, MountainBike's setGear gets executed.

痞味浪人 2025-01-05 13:42:03

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

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

More generally, you should not let an object reference escape it's constructor, be it by passing "this" as a parameter to another class's method or by calling methods that can be overridden.

You should not call overridden methods from the superclass constructor even though you can. The reason is that the super class's constructor is run before the subclass's and the object state may be inconsistent. For example final fields in the subclass are not set yet.

安人多梦 2025-01-05 13:42:03

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

class A{methodA...}
class B extends A{methodA...}
A a=new B;
a.methodA(); <<<< this should call B's methodA

Yes, overriding the base class method to create and accommodate new functionality in the derived class is what defines the subtype - polymorphic feature.

class A{methodA...}
class B extends A{methodA...}
A a=new B;
a.methodA(); <<<< this should call B's methodA
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文