Могу ли я расширить класс и переопределить вложенный тип enum? - PullRequest
15 голосов
/ 08 июня 2011

Если у меня есть класс, который содержит тип 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();

Ответы [ 3 ]

26 голосов
/ 13 июля 2011

Вы не можете продлить 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);
    }
}

Voila!


Если вы хотите потребовать , чтобы тип был Color и был перечислением, используйте эту границу:

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

Или любопытный эквивалент:

class Vehicle<T extends Enum<? extends Color>> { ...
8 голосов
/ 08 июня 2011

Могу ли я расширить этот класс и переопределить тип перечисления или добавить дополнительные константы к этому перечислению?

Проблема в вашей ситуации называется сокрытием , а не переопределяет перечисления, а два перечисленных выше не связаны друг с другом.Если вы указали переопределение как , расширяющее тип перечисления, поскольку перечисление уже объявлено с ключевым словом final, вы не можете создать подтип типа перечисления, чтобы добавить больше констант.

Цель состоит в том, чтобы пользователь мог вызывать метод getColor (), не зная, принадлежит ли динамический объект базовому классу или производному классу

Вы неверны впереопределение метода getColor.Тем не менее, вы сделали этот метод в подклассе RacingCar имеет ту же сигнатуру, что и метод в суперклассе Car.Вы все еще забыли о типе возврата , который должен совпадать с типом возврата в суперклассе или быть подтипом типа возвращаемого значения переопределенного метода.У нас есть два разных перечисления, которые имеют одно имя CarColors.Другими словами, полное имя перечисления в подклассе - RacingCar.CarColors, а в суперклассе - Car.CarColors.Итак, вы нарушили правило переопределения методов, а не того же типа возвращаемого значения и не подтипа возвращаемого типа суперкласса.

В этом случае мы не можем создать подтип, и вы не хотите вставлятьЖЕЛТЫЙ для перечисления CarColors в суперклассе Car, вот мое решение.

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, что интерфейс является супертипом двух перечислений втвой пример.Это решение полностью соответствует вашим ожиданиям, но может оказаться сложным.

0 голосов
/ 13 июля 2011

Enums - это точно конечные внутренние классы, которые расширяются java.lang.Enum<E>.Вы не можете расширять, переопределять или наследовать enum.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...