简体   繁体   中英

How to pass generic enum key in Java code

I have two classes ie ChildOne & ChildTwo which are extending Base class need Base and an enum named AgeEnum . There is one method ie getAge() is common in child classes, Now I want to move that common method in the base class also I want to do something so that when I call getAge() on any of the objects (ex - ChildOne.getAge() ) it should return age of that child define in enum.

  • Base Class

      public class BaseClass { ***// Define getAge() here somehow to get the dynamic value of the*** } 
  • Child One Class

      public class ChildOne extends BaseClass { public int getAge(){ return AgeEnum.ChildAge.CHILD_ONE.getValue(); } } 
  • Child Two Class

      public class ChildTwo extends BaseClass { public int getAge(){ return AgeEnum.ChildAge.CHILD_TWO.getValue(); } } 
  • Enum

      public class AgeEnum { public enum ChildAge { CHILD_ONE(12), CHILD_TWO(19); private ChildAge(final int text) { this.text = text; } private final int text; public int getValue() { return text; } } } 

So far I have analyzed that if we could do something like this, but how to configure this in enum call, in this case if I call getAge() of child class I will get the value from enum all I have to do is identify the child class and pass enum constant if that class at run time (may be I will get the class instance from the context and get the class name using reflection) :

     public class BaseClass {
        public int getAge(){
            return AgeEnum.ChildAge.<dynamicAgeConstent>.getValue();
        }
     }

One way would be to let the enum be an attribute of the base class. This attribute might come as an argument to the constructor of the base class:

public class BaseClass {

    private final AgeEnum.ChildAge age;

    public BaseClass(AgeEnum.ChildAge age) {
        this.age = age;
    }

    public int getAge() {
        return this.age.getValue();
    }
}

Then, subclasses would only need to specify the correct enum:

public class ChildOne extends BaseClass {

    public ChildOne() {
        super(AgeEnum.ChildAge.CHILD_ONE);
    }
}

And:

public class ChildTwo extends BaseClass {

    public ChildTwo() {
        super(AgeEnum.ChildAge.CHILD_TWO);
    }
}

First, let's start with the most obvious solution. Since your task does not assume that there could be BaseClass instances that are neither ChildOne nor ChildTwo , there is no need to move the implementation up the class hierarchy at all. Apparently, you want to make the method available at the base type, which works easily by declaring the base type abstract :

public abstract class BaseClass {
    public abstract int getAge();
}
public class ChildOne extends BaseClass {
    @Override public int getAge(){
        return AgeEnum.ChildAge.CHILD_ONE.getValue();
    }
}
public class ChildTwo extends BaseClass {
    @Override public int getAge(){
        return AgeEnum.ChildAge.CHILD_TWO.getValue();
    }
}

Generally, it's possible and recommended to structure the code to minimize the code duplication, eg

public abstract class BaseClass {
    public int getAge() {
        return childAge().getValue();
    }
    abstract AgeEnum.ChildAge childAge();
}
public class ChildOne extends BaseClass {
    @Override AgeEnum.ChildAge childAge() {
        return AgeEnum.ChildAge.CHILD_ONE;
    }
}
public class ChildTwo extends BaseClass {
    @Override AgeEnum.ChildAge childAge() {
        return AgeEnum.ChildAge.CHILD_TWO;
    }
}

but here, the code duplication is so small that it is not worth the raised complexity of having two methods now.

For completeness, it is possible to make these association a fixed static property of the subclasses, queryable by the base class implementation

public abstract class BaseClass {
    @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE)
    @interface Age { AgeEnum.ChildAge value(); }

    public int getAge() {
        return getClass().getAnnotation(Age.class).value().getValue();
    }
}

@Age(AgeEnum.ChildAge.CHILD_ONE)
public class ChildOne extends BaseClass {
}

@Age(AgeEnum.ChildAge.CHILD_TWO)
public class ChildTwo extends BaseClass {
}

but, it's again questionable whether the raised complexity pays off in these simple cases. I think, you just need the base class to be abstract , like in the first example…

You can get enum constants by their name, such as

ChildAge enumConstant = ChildAge.valueOf("CHILD_ONE");

you can then use something like:

System.out.println(ChildAge.valueOf("CHILD_ONE").getValue());

which prints 12.

If you really want to "connect" your subclasses to an enum constant, I would simply hardcode them since you (can only) hardcode a subclass as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM