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


8

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

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%)。

代码如下所示。特别要注意的是,“叶”类本身非常整洁 - 但泛型类的声明非常丑陋。没关系:你只写一次。一旦泛型类在那里,那么使用它们很容易。

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

  • 提供返回 单实例,但类型根据 父/子
  • 返回一个实例 每个括号/孩子,适当类型的 ,并包括一个在 每个父级枚举

第二种选择是,“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; 
    } 
} 
  0

这不是一个真正的问题,但它可能是值得重新措词的问题,你回答自己,所以我们可以投票。 22 2月. 092009-02-22 07:57:58

  0

这不是一个问题,但我确实认为这里有一些地方可以解决这个问题。我知道杰夫不喜欢这个主意,尽管如此,你可能会发火。 22 2月. 092009-02-22 08:12:23

  0

我不得不同意以前的评论,将其写成问题会更好(请记住,您可以回答自己的问题)。 22 2月. 092009-02-22 08:24:19

+2

我不同意SO是这种事情的地方。这真是一篇博文。如果它可以写成一个问题,那么写下这个问题 - 如果这是一个好的解决方案,它会被投票,如果有更好的解决方案,那么它不会。 -1我担心,如果可以的话,我会投票结束。 22 2月. 092009-02-22 09:01:50

  0

未找到问题? 22 2月. 092009-02-22 11:27:11

  0

@Nick Fortescue杰夫说他想创造SO作为一个不喜欢博客分享知识的人的地方。 22 2月. 092009-02-22 12:58:26

  0

@IainMH - 我知道,但对于问题的答案。杰夫仍然写博客文章。这个很接近边界线,但我认为如果作者不能将其改写为问题,那么它应该被关闭。如果它是什么意思,它可以作为一个问题改写 22 2月. 092009-02-22 22:16:15

  0

是问题 - 问题是什么? 25 2月. 092009-02-25 11:17:52

  0

嗯,我不会阻止,因为我不够酷,每天都有些有趣的事情要说。或一周。所以我做了这个帖子。 28 2月. 092009-02-28 02:54:35

  0

如果以问题的答案作为回答,这将会很好。 27 7月. 112011-07-27 21:21:59

1

你可以只使用共享枚举执行,而不是:

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

,它允许您创建枚举的,然后可以被继承。

  0

真正的枚举虽然有好处,就像在它们上切换()的能力一样。 11 7月. 092009-07-11 03:28:33

  0

真正的枚举也是由java序列化特别处理的。 16 2月. 112011-02-16 08:08:43


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

关键是不必将东西投入枚举 - 在编译时使其具有类型安全性。 22 6月. 112011-06-22 03:25:41