简体   繁体   English

使用通用类型Enum创建EnumMap

[英]Creating an EnumMap with a generic type Enum

If I have a bunch of classes that all contain an Enum and EnumMap and I want to create a superclass for those classes. 如果我有一堆包含Enum和EnumMap的类,我想为这些类创建一个超类。

public interface ColorEnum {
}

class ColorMarbles extends Toy {
    enum MARBLE implements ColorEnum
        { BLUE, GREEN }
    EnumMap<MARBLE, String> names = new EnumMap<MARBLE, String>(MARBLE.class);
    //stuff
    // fields

    public void populate(ArrayList<String> designer) {
        int i = 0;
        for(MARBLE marble : MARBLE.values()) {
            marble.name = designer.get(i);
            i++;
        }
    }
}

class ColorBalloons extends Toy {
    enum BALLOON implements ColorEnum
        { YELLOW, RED }
    EnumMap<BALLOON, String> names = new EnumMap<BALLOON, String>(BALLOON.class);
    //stuff
    // fields

    public void populate(ArrayList<String> designer) {
        int i = 0;
        for(BALLOON balloon : BALLOON.values()) {
            balloon.name = designer.get(i);
            i++;
        }
    }
}

How do I make create a superclass to have a generic EnumMap that contains an enum of type ColorEnum like this? 如何创建一个超类,使其包含一个包含类似ColorEnum类型的枚举的通用EnumMap?

public abstract class Toy {
    EnumMap<ColorEnum, String> names;
}

eidt: I realize that I was too vague with my example. eidt:我意识到我的例子太模糊了。 Dogs are probably a bad example. 狗可能是一个坏榜样。 I change it to something hopefully more clear. 我把它改成希望更清楚的东西。

What I have is a bunch of classes with methods like populate which populates the EnumMap. 我所拥有的是一堆类,其中包含填充EnumMap的populate等方法。 The names are in a predefined order. 名称按预定义顺序排列。 Instead of defining populate in every class, I'm hoping to be able to bring it to the Toy superclass so I don't have to keep copy-pasting in each new class type Toy. 我不希望在每个类中定义填充,而是希望能够将它带到Toy超类中,因此我不必在每个新类类型的Toy中保留复制粘贴。

Hopefully this will explain more what I'm looking for. 希望这能解释更多我正在寻找的东西。

I have a feeling your design is needlessly overcomplicated. 我觉得你的设计不必要地过于复杂。

With enums 随着枚举

If you don't require a class inheritance, you can work with enums directly as with top level classes. 如果您不需要类继承,则可以像使用顶级类一样直接使用枚举。

public interface Animal {}

public enum Dog implements Animal {
    HUSKY("Husky"), LAB("Labrador");

    private final String name;

    Dog(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

Enums can declare fields, methods and implement interfaces like any other Java classes. 枚举可以像任何其他Java类一样声明字段,方法和实现接口。 Their only limitation is that their direct superclass is always java.lang.Enum and they can't be extended. 他们唯一的限制是他们的直接超类总是java.lang.Enum并且它们不能被扩展。

However every enum constant can have its own set of unique data passed to its constructor. 但是,每个枚举常量都可以将自己的一组唯一数据传递给它的构造函数。 It is even possible that each of the constants can override a common method of that enum with its unique implementation. 甚至可能每个常量都可以通过其独特的实现覆盖该枚举的常用方法。

A nice tutorial explaining more about the full power of enums: http://javarevisited.blogspot.cz/2011/08/enum-in-java-example-tutorial.html 一个很好的教程,解释更多关于枚举的全部功能: http//javarevisited.blogspot.cz/2011/08/enum-in-java-example-tutorial.html


Without enums 没有枚举

In case you need an actual class inheritance for sharing some common methods (for example from the Animal superclass), I still would drop the map approach and rather try something more OOP oriented: 如果你需要一个实际的类继承来共享一些常见的方法(例如来自Animal超类),我仍然会放弃map方法,而是尝试更多面向OOP的方法:

public class Animal {
}

public abstract class Dog extends Animal {

    public abstract String getName();

    public static class Husky extends Dog {
        @Override
        public String getName() {
            return "husky";
        }
    }

    public static class Lab extends Dog {
        @Override
        public String getName() {
            return "labrador";
        }
    }

}

One mechanism I have used for something like this is to extend a generic base class that has a generic parameter that allows you to pass the Enum details up to it. 我用过这种方法的一种机制是扩展一个通用基类,它具有一个通用参数,允许你将Enum细节传递给它。

This example defines a base Table class for database tables: 此示例为数据库表定义基本Table类:

public class Table<Column extends Enum<? extends Column>> {
  // Name of the table.
  protected final String tableName;
  // All of the columns in the table. This is actually an EnumSet so very efficient.
  protected final Set<Column> columns;

  /**
   * The base interface for all Column enums.
   */
  public interface Columns {
    // What type does it have in the database?
    public Type getType();
  }

  // Small list of database types.
  public enum Type {
    String, Number, Date;
  }

  public Table(String tableName,
               Set<Column> columns) {
    this.tableName = tableName;
    this.columns = columns;
  }

}

Now you can subclass this: 现在你可以继承这个:

public class VersionTable extends Table<VersionTable.Column> {

  public enum Column implements Table.Columns {
    Version(Table.Type.String),
    ReleaseDate(Table.Type.Date);

    // Sadly all of this must be in ALL of your enums but most of the work can be pushed up to `Table`
    final Table.Type type;

    Column(Table.Type type) {
      this.type = type;
    }

    @Override
    public Type getType() {
      return type;
    }
  }

  public VersionTable() {
    super("Versions", EnumSet.allOf(Column.class));
  }
}

and make use of functionality in the parent class that handles your enum. 并使用处理枚举的父类中的功能。

Note here I am passing an EnumSet to the Table constructor. 请注意,我将EnumSet传递给Table构造函数。 I am sure you could change this to accommodate your EnumMap requirement if you decide an EnumSet is insufficient. 如果您确定EnumSet不足,我相信您可以更改此项以适应您的EnumMap要求。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM