当枚举属性由于新继承而始终具有相同的值时,我是否应该保留它?

Should I keep an enum attribute when it has always the same value as a result of a new inheritance?

我有这些 classes:

enum Brand {
    FORD, FERRARI, TESLA, RENAULT;
}
public class Car {
    Brand brand;
    String plate;
    ...
}
//getters and setters

想象一下,出于某种原因,我需要为两个新的 class 将 Car 设为超级class:CombustionCar 和 ElectricCar。新要求之一是 ElectricCar 的品牌属性必须始终是 TESLA 值,而不是任何其他值。 我想到了一些解决方案:

  1. 我可以在 superclass 汽车上保留品牌属性,并让 ElectricCar 构造函数设置 TESLA 品牌。但是这种方式可以让我在创建对象后设置一个新品牌
public class ElectricCar extends Car {
    public ElectricCar(...){
    super(Brand.TESLA, ...);
}

ElectricCar ec = new ElectricCar(...);
ec.setBrand(Brand.FORD);
  1. 我可以从 superclass 中取出 Brand attr 并将其设置在两个 subclasses 上,但在 ElectricCar 中将其设置为带有 final 的 class 属性,这样任何人都可以能够设置一个新值
public class ElectricCar extends Car {
    public static final Brand brand = Brand.TESLA;
    ...
}
public class CombustionCar extends Car {
    private Brand brand;
    ...
}
  1. 避免继承并使用组合,但是有了这个我将无法使用,例如,包含以下两者的列表:
public class ElectricCar {
    private Car car;
    private Brand brand = Brand.TESLA;//with no setter
    ...
}
public class CombustionCar {
    private Car car;
    private Brand brand;
    ...
}

我正在寻求最优雅、最可维护的解决方案,我认为它们中的任何一个都可以很好地解决我的问题。

您的第一个解决方案不正确,因为您需要电动汽车的不可编辑品牌。

你的第二个解决方案根本不起作用,除非你覆盖品牌字段的 getter 和 setter 以使用你的静态字段,这不是“优雅和可维护的”

您的第三个解决方案没有使用面向对象的概念。

我会使用的一个简单解决方案是让字段品牌及其 getter 在 Car superclass 中,但我只会在 CombustionCar [=] 中定义 setter 31=]。 或者,如果你扩展你的模型,你可以创建一个中间抽象 superclass "FreeBrandCar" 来实现 setter.

在 CombustionCar 中使用 setter 的解决方案

abstract public class Car {
    protected String brand;
    protected Car(final String b) {
        this.brand = b;
    }
    public String getBrand() {
        return this.brand;
    }
}

public class ElectricCar extends Car {
    public ElectricCar() {
        super("Tesla");
    }
}

public class CombustionCar extends Car {
    public CombustionCar(final String b) {
        super(b);
    }
    public void setBrand(final String b) {
        this.brand = b;
    }
}

具有中间体的解决方案class

abstract public class Car {
    protected String brand;
    protected Car(final String b) {
        this.brand = b;
    }
    public String getBrand() {
        return this.brand;
    }
}

abstract public class FreeBrandCar extends Car {
    public FreeBrandCar (final String b) {
        super(b);
    }
    public void setBrand(final String b) {
        this.brand = b;
    }
}

public class ElectricCar extends Car {
    public ElectricCar() {
        super("Tesla");
    }
}

public class CombustionCar extends FreeBrandCar {
    public CombustionCar(final String b) {
        super(b);
    }
}

它尊重您的要求:

public void test() {
    ElectricCar ec = new ElectricCar();
    ec.setBrand("..."):  // Doesn't compile
    CombustionCar cc = new CombustionCar("Ford"); // OK
    cc.setBrand("Fiat"); // OK
    Arrays.asList(ec, cc)
       .stream()
       .forEach(car -> System.out.println(car.getBrand())); // prints Tesla and Fiat
}