编码提示 - 交集类型和java枚举

时间:2009-02-22 07:34:39

标签: java generics enums

交集类型允许您(有点排序)执行具有继承层次结构的枚举。您不能继承实现,但可以将其委托给辅助类。

enum Foo1 implements Bar {}
enum Foo2 implements Bar {}

class HelperClass {
   static <T extends Enum<T> & Bar> void fooBar(T the enum) {}
}

当您有许多实现某种模式的不同枚举时,这很有用。例如,有许多具有父子关系的枚举对。

enum PrimaryColor {Red, Green, Blue;}
enum PastelColor {Pink, HotPink, Rockmelon, SkyBlue, BabyBlue;}

enum TransportMedium {Land, Sea, Air;}
enum Vehicle {Car, Truck, BigBoat, LittleBoat, JetFighter, HotAirBaloon;}

您可以编写通用方法,说“好的,给定一个枚举值,该值是某些其他枚举值的父级,子类型的所有可能子枚举中有多少百分比将此特定父值作为其父级?”,以及拥有所有类型安全和没有铸造完成。 (例如:“Sea”占所有可能车辆的33%,而“Green”占所有可能车辆的20%)。

代码看起来像这样。特别要注意的是“叶子”类本身非常简洁 - 但泛型类的声明非常难看。没关系:你只写一次。一旦通用类存在,那么使用它们很容易。

下面的助手类只有一些静态方法。其他方法包括

  • 提供返回a的实例 单身,但打字按照 父母/子女
  • 返回一个实例 为每个paren /孩子打字 适当的,包括一个 每个家长枚举

使用第二个选项,“children”对象实际上将位于帮助器内,因此减少了枚举中所需的代码量。他们都会实例化一个帮助者,并将任何困难的事情委托给他们。

import java.util.EnumSet;

import javax.swing.JComponent;

public class zz extends JComponent {

    public static void main(String[] args) {
        System.out.println(PrimaryColor.Green + " " + ParentUtil.pctOf(PrimaryColor.Green) + "%");
        System.out.println(TransportMedium.Air + " " + ParentUtil.pctOf(TransportMedium.Air) + "%");
    }


}

interface Parent<P extends Enum<P> & Parent<P, C>, C extends Enum<C> & Child<P, C>> {
    Class<C> getChildClass();

    EnumSet<C> getChildren();
}

interface Child<P extends Enum<P> & Parent<P, C>, C extends Enum<C> & Child<P, C>> {
    Class<P> getParentClass();

    P getParent();
}

enum PrimaryColor implements Parent<PrimaryColor, PastelColor> {
    Red, Green, Blue;

    private EnumSet<PastelColor>    children;

    public Class<PastelColor> getChildClass() {
        return PastelColor.class;
    }

    public EnumSet<PastelColor> getChildren() {
        if(children == null) children=ParentUtil.loadChildrenOf(this);
        return children;
    }
}

enum PastelColor implements Child<PrimaryColor, PastelColor> {
    Pink(PrimaryColor.Red), HotPink(PrimaryColor.Red), //
    Rockmelon(PrimaryColor.Green), //
    SkyBlue(PrimaryColor.Blue), BabyBlue(PrimaryColor.Blue);

    final PrimaryColor  parent;

    private PastelColor(PrimaryColor parent) {
        this.parent = parent;
    }

    public Class<PrimaryColor> getParentClass() {
        return PrimaryColor.class;
    }

    public PrimaryColor getParent() {
        return parent;
    }
}

enum TransportMedium implements Parent<TransportMedium, Vehicle> {
    Land, Sea, Air;

    private EnumSet<Vehicle>    children;

    public Class<Vehicle> getChildClass() {
        return Vehicle.class;
    }

    public EnumSet<Vehicle> getChildren() {
        if(children == null) children=ParentUtil.loadChildrenOf(this);
        return children;
    }
}

enum Vehicle implements Child<TransportMedium, Vehicle> {
    Car(TransportMedium.Land), Truck(TransportMedium.Land), //
    BigBoat(TransportMedium.Sea), LittleBoat(TransportMedium.Sea), //
    JetFighter(TransportMedium.Air), HotAirBaloon(TransportMedium.Air);

    private final TransportMedium   parent;

    private Vehicle(TransportMedium parent) {
        this.parent = parent;
    }

    public Class<TransportMedium> getParentClass() {
        return TransportMedium.class;
    }

    public TransportMedium getParent() {
        return parent;
    }
}

class ParentUtil {
    private ParentUtil(){}
    static <P extends Enum<P> & Parent<P, C>, C extends Enum<C> & Child<P, C>> //
    float pctOf(P parent) {
        return (float) parent.getChildren().size() / //
                (float) EnumSet.allOf(parent.getChildClass()).size() //
                * 100f;
    }
    public static <P extends Enum<P> & Parent<P, C>, C extends Enum<C> & Child<P, C>> //
    EnumSet<C> loadChildrenOf(P p) {
        EnumSet<C> cc = EnumSet.noneOf(p.getChildClass());
        for(C c: EnumSet.allOf(p.getChildClass())) {
            if(c.getParent() == p) {
                cc.add(c);
            }
        }
        return cc;
    }
}

2 个答案:

答案 0 :(得分:1)

您可以使用Commons Enum实现:

http://commons.apache.org/lang/api-2.3/org/apache/commons/lang/enums/Enum.html

允许您创建可以进行子类化的Enum。

答案 1 :(得分:0)

这更简单,它能做你想做的吗?

import java.util.*;
interface Tree{
    Tree parent();
    Set<Tree> children();
}
enum PrimaryColor implements Tree {
    Red,Green,Blue;
    @Override public Tree parent() {
        return null;
    }
    @Override public Set<Tree> children() {
        return Collections.unmodifiableSet(children);
    }
    final Set<Tree> children=new LinkedHashSet<Tree>();
}
enum PastelColor implements Tree {
    Pink(PrimaryColor.Red),HotPink(PrimaryColor.Red),Rockmelon(PrimaryColor.Green),SkyBlue(PrimaryColor.Blue),BabyBlue(PrimaryColor.Blue);
    PastelColor(final PrimaryColor primaryColor) {
        this.primaryColor=primaryColor;
        if (primaryColor!=null) primaryColor.children.add(this);
    }
    @Override public Tree parent() {
        return primaryColor;
    }
    @Override public Set<Tree> children() {
        return Collections.emptySet();
    }
    double percent() {
        return primaryColor.children().size()*100./EnumSet.allOf(super.getClass()).size();
    }
    private final PrimaryColor primaryColor;
}
public class Main{
    static double percent(final Tree tree) {
        final Tree parent=tree.parent();
        if (tree instanceof Enum) { return parent.children().size()*100./((Enum)tree).getClass().getEnumConstants().length; }
        else throw new RuntimeException("strange tree!");
    }
    public static void main(String[] args) {
        System.out.println("one way");
        for(PastelColor pastelColor:PastelColor.values())
            System.out.println(pastelColor+" "+pastelColor.percent());
        System.out.println("another way");
        for(PastelColor pastelColor:PastelColor.values())
            System.out.println(pastelColor+" "+percent(pastelColor));
    }
}