Кодирование - типы пересечений и перечисления java


8

Типы перекрестков позволяют вам (kinda sorta) делать перечисления, имеющие иерархию наследования. Вы не можете наследовать реализацию, но можете делегировать ее классу-помощнику.

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% от всех возможных пастелей).

Код выглядит следующим образом. Обратите внимание, в частности, что сами «листовые» классы довольно аккуратные, но у общих классов есть декларации, которые ужасно уродливы. Это нормально: вы только пишете их один раз. Как только общие классы существуют, их легко использовать.

У вспомогательного класса ниже есть несколько статических методов. Другие способы пойти включают

  • обеспечивая экземпляр, который возвращает синглтона, но набраны в соответствии с родителем/ребенком
  • возвращающего экземпляр для каждого скобка/ребенка, набранных надлежащим образом, и в том числе один в каждого родитель перечисление

при этом втором варианте, «дети» объект будет фактически внутри помощник, таким образом уменьшая количество коды, необходимое в перечислениях. Все они создавали помощника и делегировали что-либо сложное.

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

  0

Это не вопрос, но я думаю, что есть место для вещей. Я знаю, что Джеффу не нравится эта идея, хотя вы можете получить пламя. 22 фев. 092009-02-22 08:12:23

  0

Я должен согласиться с предыдущими комментариями, было бы намного лучше, если бы это было написано как вопрос (помните, что вы можете отвечать на свои вопросы). 22 фев. 092009-02-22 08:24:19

+2

Я не согласен, что это место для такого рода вещей. Это действительно сообщение в блоге. Если это может быть написано как вопрос, тогда напишите вопрос - если это хорошее решение, оно будет проголосовано, если есть лучшее решение, то это не будет. -1 Боюсь, и я проголосовал бы, чтобы закрыть, если бы мог. 22 фев. 092009-02-22 09:01:50

  0

Вопрос не найден? 22 фев. 092009-02-22 11:27:11

  0

@Nick Fortescue Джефф сказал, что он хотел создать SO как место для людей, которые не склонны к блогу, чтобы делиться своими знаниями. 22 фев. 092009-02-22 12:58:26

  0

@IainMH - Я знаю, но для ответов на вопросы. Джефф все еще пишет записи в блогах.Это очень близко к границе, но я думаю, что если автор не может переписать в качестве вопроса, тогда он должен быть закрыт. Если это то, для чего предназначен SO, его можно перефразировать как вопрос 22 фев. 092009-02-22 22:16:15

  0

Возникает вопрос - в чем вопрос? 25 фев. 092009-02-25 11:17:52

  0

Ну, я не блокирую, потому что я просто не достаточно крут, чтобы что-то интересное сказать каждый день. Или неделю. Поэтому я сделал это как сообщение. 28 фев. 092009-02-28 02:54:35

  0

Это было бы хорошо, если бы он был сформулирован как ответ на вопрос. 27 июл. 112011-07-27 21:21:59

1

Вы можете просто использовать реализацию фонда Enum вместо:

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

, который позволяет создавать Enum о том, что может быть подклассы.

  0

Реальные перечисления имеют преимущества, хотя, как способность переключаться() на них. 11 июл. 092009-07-11 03:28:33

  0

Настоящие перечисления также обрабатываются специально с помощью сериализации Java. 16 фев. 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 июн. 112011-06-22 03:25:41