代码之家  ›  专栏  ›  技术社区  ›  paulmurray

编码提示交集类型和Java枚举[关闭]

  •  8
  • paulmurray  · 技术社区  · 16 年前

    交叉类型允许您(有点)做具有继承层次结构的枚举。您不能继承实现,但可以将其委托给助手类。

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

    您可以编写泛型方法,说明“好,给定一个枚举值作为某些其他枚举值的父级,子类型的所有可能的子枚举中有多少百分比将此特定的父级值作为其父级?”,并使它的所有类型安全和没有铸造。(例如:“海”占所有可能的交通工具的33%,而“绿”占所有可能的粉彩的20%)。

    代码看起来像这样。特别注意,“Lead”类本身是非常整洁的,但是泛型类有非常丑陋的声明。没关系,你只写一次。一旦泛型类存在,就很容易使用它们。

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

    • 提供返回 单打,但根据 父/子
    • 返回实例 对于每个paren/child,键入 适当地,包括一个 每个父枚举

    有了第二个选项,“children”对象实际上就在helper中,因此减少了枚举中所需的代码量。他们都会实例化一个助手,并委派任何困难的任务。

    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 回复  |  直到 11 年前
        1
  •  1
  •   Jonathan Holloway    15 年前

    您可以只使用公有枚举实现,而不是:

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

    它允许您创建枚举,然后可以对其进行子类化。

        2
  •  0
  •   Ray Tayek    14 年前

    这更简单,它能满足你的要求吗?

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