Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I extend a class and override enclosed enum type?

Tags:

java

enums

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();
like image 828
Orit Avatar asked Jun 08 '11 16:06

Orit


2 Answers

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>> { ...
like image 53
Bohemian Avatar answered Oct 14 '22 02:10

Bohemian


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.

like image 23
Hung Tran Avatar answered Oct 14 '22 03:10

Hung Tran