【问题标题】:Can I extend a class and override enclosed enum type?我可以扩展一个类并覆盖封闭的枚举类型吗?
【发布时间】:2011-09-11 01:11:40
【问题描述】:

如果我有一个包含enum 类型的类,我可以扩展这个类并覆盖枚举类型或向这个枚举添加更多常量吗? 目的是用户可以在不知道动态对象是来自基类还是派生类的情况下调用getColor() 方法。 例如:

public class Car {

    private String name;

    private CarColors color;

    public enum CarColors {
        BLUE,
        GREEN
    }

    public Car(CarColors c) {
        color=c;
    }

    public CarColors getColor() {
        return color;
    }
}

public class RacingCar extends Car {

    private CarColors color;

    public RacingCar(CarColors c) {
        color=c;
    }

    public enum CarColors {
        BLUE,
        GREEN,
        RED
    }

    @Override //?????
    public CarColors getColor() {
        return color;
    }
}

主要是:

Car racingCar = new RacingCar();
CarColors color = racingCar.getColor();

【问题讨论】:

标签: java enums


【解决方案1】:

您不能扩展enum。枚举本质上是一个final 类。然而,枚举可以实现,所以结合泛型,你会得到:

interface Color{

}
enum CarColor implements Color{
    BLUE,
    GREEN;
}
enum RacingCarColor implements Color{
    BLUE,
    GREEN,
    YELLOW;
}
class Vehicle<T extends Color> {
    protected T color;
    protected Vehicle(T color){
        this.color = color;
    }
    public T getColor(){
        return color;
    }
}

class Car extends Vehicle<CarColor>{ 
    public Car(CarColor color){
        super(color);
    }
}

class RacingCar extends Vehicle<RacingCarColor>{ 
    public RacingCar(RacingCarColor color){
        super(color);
    }
}

瞧!


如果你想要求类型是Color并且是一个枚举,使用这个绑定:

class Vehicle<T extends Enum<T> & Color> { ...

或者一个奇怪的等价物:

class Vehicle<T extends Enum<? extends Color>> { ...

【讨论】:

  • 为此添加泛型非常有帮助。谢谢你。 :)
  • 由于某种原因在使用 java 7 的 eclipse 中,我不得不这样做, & Colour> 因为它告诉我“类型 Enum 不是一个不能指定的接口作为绑定参数”
  • @user779420 这是我的错误:规则是如果 class 是交集的边界之一,则必须首先列出它。 (我在我的 iPhone 上输入了它——没有编译器可以检查)。谢谢
  • @Bohemian 哈哈,几年前的事了,没想到会有回应!不过谢谢
【解决方案2】:

Enums 正是扩展java.lang.Enum&lt;E&gt; 的最终内部类。您不能扩展、覆盖或继承 enum

【讨论】:

    【解决方案3】:

    我可以扩展这个类并覆盖枚举类型或向这个枚举添加更多常量吗?

    您遇到的问题称为 hiding 而不是 overriding 枚举,并且上述两个枚举彼此不相关。如果您将 overriding 称为 extending 枚举类型,因为枚举已使用关键字 final 声明,您无法创建枚举类型的子类型来添加更多常量.

    目的是用户可以在不知道动态对象是来自基类还是派生类的情况下调用 getColor() 方法

    您在覆盖 getColor 方法时是不正确的。尽管如此,您已经使子类 RacingCar 中的此方法与超类 Car 中的方法具有相同的签名。您仍然忘记了 返回类型,它必须与超类中的返回类型相同,或者是被覆盖方法的返回类型的子类型。我们有两个不同的枚举,它们共享同一个名称 CarColors。换句话说,子类中枚举的完整限定名是 RacingCar.CarColors,超类中是 Car.CarColors。到目前为止,您已经打破了覆盖方法的规则,即不是相同的返回类型,也不是超类返回类型的子类型。

    在这件事上,我们无法创建子类型,并且您不想在超类 Car 的枚举 CarColors 中插入 YELLOW,这是我的解决方案。

    interface IColor{
    
    }
    enum CarColors implements IColor{
        BLUE,
        GREEN;
    }
    enum RacingCarColors implements IColor{
        BLUE,
        GREEN,
        YELLOW;
    }
    class Car {
        protected IColor color;
        public Car(IColor color){
            this.color = color;
        }
        public IColor getColor(){
            return color;
        }
    }
    class RacingCar extends Car{
        public RacingCar(IColor color){
            super(color);
        }
        public IColor getColor(){
            return color;
        }
    }
    
    
    
    public class Test{
        public static void main(String[] args) {
            Car car = new RacingCar(RacingCarColors.YELLOW);
            System.out.println(car.getColor());
    
        }
    }
    

    该方法仍然覆盖方法 getColor,但我使用了一个相同的返回类型 IColor,该接口是您示例中两个枚举的超类型。此解决方案完全符合您的期望,但这可能会很复杂。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多