【问题标题】:Should I use a superclass' setters to initialise its instance variables from a subclass?我应该使用超类的设置器从子类初始化其实例变量吗?
【发布时间】:2015-03-02 23:57:03
【问题描述】:

我有一个超类“Vehicle”及其子类“Car”,如下所示。我想从子类 Car 的构造函数中初始化变量“wheels”。我无法通过 super() 调用设置变量,因为它依赖于对方法的调用。

在这里使用超类的 setter 方法是否安全? 如果不是,类之间关系的OO基础有问题吗?

ps。尝试原谅笨拙的车辆/汽车/底盘示例,并假设在构造函数之外调用“findNumberOfWheels”方法是必要的。

车辆类别

public abstract class Vehicle {

    private int wheels;
    private Chassis chassis;

    public Vehicle(Chassis chassis){
       this.chassis = chassis;
    }

    public int getWheels() {
       return wheels;
    }

    public void setWheels(int wheels) {
       this.wheels = wheels;
    }

    public Chassis getChassis() {
       return chassis;
    }

    public void setChassis(Chassis chassis) {
       this.chassis = chassis;
    }

}

汽车类

public class Car extends Vehicle{

    public Car(Chassis chassis) {
        super(chassis);
        setWheels(findNumberofWheels(chassis));
    }

    private int findNumberofWheels(Chassis chassis){
        return chassis.getWheels();
    }

}

【问题讨论】:

  • 没关系,你不需要重写子类的getter/setter,它的行为方式是一样的。
  • 如果有人打电话给Car.setWheels(70)怎么办?如果可能,您应该避免向基本类型的接口添加突变器。通过构造函数注入轮子的数量,使属性final 会更安全。
  • 查看 Jon Skeet 对此主题的看法:stackoverflow.com/a/4893604/1980909
  • findNumberOfWheels() 对我来说似乎是一种实用方法,因为它既不使用 Vehicle 也不使用 Car 的任何属性。如果在现实中是这样,那么它应该被声明为静态的,要么在Car 类中,要么在其他地方。如果它是静态的,您可以在对 super() 的调用中内联它的调用,并将其作为参数传递给超类的构造函数,所以我认为不需要调用 setter。
  • 这段代码似乎有问题——底盘定义了轮子的数量chassis.getWheels();,所以这是一个委托案例。没有必要在 Car 和 Vehicle 中维护重复属性

标签: java inheritance


【解决方案1】:

如果您可以通过子类构造超类,那么您肯定可以使用它的 setter。

我猜您的替代方法是将这些调用移到构造函数之外,并在每次实例化新的Car 时调用setWheels?您绝对不想这样做,因为您会重复自己,而您(或其他人)可能会忘记拨打电话。您应该将尽可能多的初始化代码放入构造函数中。这样,如果你需要改变它,你只需要在一个地方改变它。

您甚至可以将超类字段设置为受保护:

protected int wheels;

并直接更改。但这取决于您自己的判断。

【讨论】:

  • 你说得对,我不想将它移到构造函数之外,因为我确实会忘记拨打电话。正如@Magnamag 指出的那样,“findNumberofWheels()”确实是一种实用方法,可以避免将代码直接放在构造函数中,因此应该声明为静态的。感谢您的帮助。
【解决方案2】:

findNumberOfWheels() 对我来说似乎是一种实用方法,因为它既不使用 Vehicle 也不使用 Car 类的任何属性。

如果在现实中是这样,那么它应该被声明为static,要么在Car 类中,要么在其他地方。如果它是static,您可以在对super() 的调用中内联它的调用并将其作为参数传递给超类的构造函数,因此我认为不需要调用setter。

一般而言,通过构造函数初始化属性并委托给实用程序方法会更安全,以防您需要在分配变量之前进行一些计算。

如果这不可能,请使用工厂模式或构建器模式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-07-27
    • 2016-06-13
    • 1970-01-01
    • 1970-01-01
    • 2016-07-28
    • 1970-01-01
    • 2019-10-12
    相关资源
    最近更新 更多