17

If I have a class that contains an enum type, can I extend this class and override the enum type or add more constants to this enum? The purpose is that user will be able to call getColor() method without knowing if the dynamic object is from base class or derived class. For example:

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

and in main:

Car racingCar = new RacingCar();
CarColors color = racingCar.getColor();
Volo
  • 28,673
  • 12
  • 97
  • 125
Orit
  • 171
  • 1
  • 1
  • 3
  • See also [Java extend enum](http://stackoverflow.com/questions/1414755/java-extend-enum), [Extending Java Enums](http://stackoverflow.com/questions/2642281/extending-java-enums), [Extending a enum in Java](http://stackoverflow.com/questions/6511453/extending-a-enum-in-java) – Paŭlo Ebermann Jul 12 '11 at 23:47

3 Answers3

33

You can't extend enum. enums are essentially a final class. However, enums can implement, so combined with generics, you get:

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!


If you want to require that the type be a Color and be an enum, use this bound:

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

Or a curious equivalent:

class Vehicle<T extends Enum<? extends Color>> { ...
Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • 1
    The addition of generics to this was very helpful. Thank you. :) –  Mar 10 '12 at 17:43
  • 1
    For some reason in eclipse using java 7, i had to do this, & Colour> because it told me that "the type Enum is not an interface it cannot be specified as a bound parameter" – user779420 Mar 26 '14 at 01:23
  • @user779420 that was my mistake: the rule is if a *class* is one one of the bounds of an intersection, it must be listed first. (I typed it in on my iPhone - no compiler to check). Thx – Bohemian Mar 26 '14 at 01:38
  • @Bohemian haha, it was a few years ago, I wasn't expecting any response! Thanks though – user779420 Mar 26 '14 at 06:00
9

Can I extend this class and override the enum type or add more constants to this enum?

The problem in your situation is called hiding rather than overriding enums, and two above enums aren't related to each other. If you referred overriding as extending an enum type, since an enum is already declared with keyword final, you can't create a sub type of an enum type to add more constants.

The purpose is that user will be able to call getColor() method without knowing if the dynamic object is from base class or derived class

You're incorrect in overriding the method getColor. Nevertheless, you've made this method in subclass RacingCar has the same signature as the method in superclass Car. You still forgot about the return type that must be same as the return type in superclass or be a subtype of the return type of the overridden method. We have two different enums that shared one name CarColors. In other words, the full qualified name of the enum in subclass is RacingCar.CarColors and in the superclass is Car.CarColors. So far you have broken the rule of overriding methods, not same return type and not a subtype of the superclass's return type.

In this matter, we can't create a subtype and you don't want to insert YELLOW to the enum CarColors in super class Car, here is my solution.

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());

    }
}

The approach is still overriding the method getColor, but I used one same return type IColor that interface is super type of two enums in your example. This solution completely matched your expectations, but this might be complicated.

Hung Tran
  • 1,595
  • 2
  • 17
  • 17
0

Enums are exactly final inner classes that extends java.lang.Enum<E>. You cannot extend, override or inherit an enum.

dhblah
  • 9,751
  • 12
  • 56
  • 92