코딩 팁 - 교차 유형 및 자바 열거 형


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

코드는 다음과 같습니다. 특히 "leaf"클래스 자체는 매우 깔끔하고 - generic 클래스에는 끔찍한 추악한 선언이 있습니다. 괜찮습니다. 한 번만 쓸 수 있습니다. 일단 제네릭 클래스가 있으면 쉽게 사용할 수 있습니다.

아래의 도우미 클래스에는 몇 가지 정적 메서드 만 있습니다. 다른 방법은 각 괄호/자녀를위한 인스턴스 을 반환하는 상위/하위

  • 에 따라 싱글을 반환하는 인스턴스를 제공

    • 을 포함 가지만 입력하기 위해 적절하게 를 입력하고, 하나를 포함 각 부모 열거 형

    이 두 번째 옵션을 사용하면 "자식"개체가 실제로 도우미 안에 들어가므로 열거 형에 필요한 코드의 양이 줄어 듭니다. 그들은 모두 도우미를 인스턴스화하고 어려운 일을 위임합니다.

    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 feb. 092009-02-22 07:57:58

      0

    이것은 질문이 아니지만 나는 그런 종류의 일을위한 장소가 있다고 생각합니다. 제프가 생각을 좋아하지 않는다는 것을 알고 있습니다.하지만 당신은 화염에 빠질 수도 있습니다. 22 feb. 092009-02-22 08:12:23

      0

    나는 이전 의견에 동의해야하며, 질문으로 작성하는 것이 훨씬 낫습니다 (자신의 질문에 대답 할 수 있음을 기억하십시오). 22 feb. 092009-02-22 08:24:19

    +2

    나는 SO가 이런 종류의 일을하는 곳이라는 것에 동의하지 않는다. 이것은 정말로 블로그 게시물입니다. 그것이 질문으로 쓰여질 수 있다면, 질문을 적으십시오. 이것이 좋은 해결책이라면 더 나은 해결책이 있다면 투표하지 않을 것입니다. -1 나는 두려워하고, 할 수만 있다면 투표를 끝내겠다. 22 feb. 092009-02-22 09:01:50

      0

    질문을 찾을 수 없습니까? 22 feb. 092009-02-22 11:27:11

      0

    @Nick Fortescue 제프는 자신의 지식을 공유하기 위해 블로그를 쓰지 않는 사람들을 위해 SO를 만들어보고 싶다고 말했습니다. 22 feb. 092009-02-22 12:58:26

      0

    @IainMH - 알아,하지만 질문에 대한 답변. Jeff는 여전히 블로그 게시물을 씁니다.이것은 경계선에 꽤 가깝 습니다만, 저자가 질문으로 다시 쓸 수 없다면 나는 닫아야한다고 생각합니다. 그것이 SO가 의미하는 것이면, 그것은 질문으로 바꿔 질 수 있습니다 22 feb. 092009-02-22 22:16:15

      0

    질문입니까? 질문은 무엇입니까? 25 feb. 092009-02-25 11:17:52

      0

    글쎄, 나는 단지 매일 말하기에 흥미로운 것을 가질만큼 충분히 냉담하지 않기 때문에 차단하지 않는다. 또는 주. 그래서 저는 이것을 게시물로 사용했습니다. 28 feb. 092009-02-28 02:54:35

      0

    질문에 대한 답으로 말하면 괜찮습니다. 27 jul. 112011-07-27 21:21:59

    1

    당신은 대신 커먼즈 열거 구현을 사용할 수 있습니다 : 당신이 열거의 다음 서브 클래스 수 만들 수 있습니다

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

    합니다.

      0

    실제 enum에는 switch() 기능과 같은 이점이 있습니다. 11 jul. 092009-07-11 03:28:33

      0

    실제 enum은 또한 자바 직렬화에 의해 특별히 처리됩니다. 16 feb. 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

    포인트가 Enum에 캐스팅 할 필요가 없습니다. 컴파일시에 타입 안전성을 갖습니다. 22 jun. 112011-06-22 03:25:41