使用枚举泛型制作代码

时间:2013-02-08 12:42:17

标签: java enums

我有一个代码,最初只为一个团队设计,他们将一个枚举[存储任务列表]传递给api。这个api然后将这个枚举的使用推进到许多其他类。

现在我有一个任务,这个代码需要多个团队使用,他们可以以枚举的形式传递自己的任务集。

鉴于当前的实现,我不认为支持多个团队完全改造代码是可行的,因为枚举不能扩展其他枚举。

有没有办法在没有大规模变化的情况下实现这个目标?

5 个答案:

答案 0 :(得分:3)

但是......枚举可以实现接口,例如:

public interface Task {
    int getPriority(); // just for example
    // plus whatever methods define a task
}

public enum Team1Task implements Task {
    Task1(1),
    Task2(3);
    private final int priority;
    private Team1Task(int priority) {
        this.priority = priority;
    }
    public int getPriority() {
        return priority;
    }
}

现在我们可以使用java通用功夫来指定一个绑定到合适枚举的通用参数:

public class TaskProcessor<T extends Enum<T> & Task> {
    public void process(T task) {
        // do something with task
    }
}

使用它:

TaskProcessor<Team1Task> p = new TaskProcessor<Team1Task>();
p.process(Team1Task.Open); // will only accept a Team1Task instance

仅供参考,作为对仿制药的好奇心,您可以使用此约束来实现同样的目的:

public class TaskProcessor<T extends Enum<? extends Task>> {

虽然我发现效果没有实际差异,但我发现它缺乏上面交叉界限的清晰度和熟悉模式。有关详情,请参阅this question

答案 1 :(得分:2)

围绕枚举的大部分工作都比较容易。

这是一个严重削减的例子。它定义了一个通用数据库Table类,它以enum Column作为定义类型。 enum定义表中的列。定义类型是enum,它还实现了一个非常有用的接口。

public class Table<Column extends Enum<Column> & Table.Columns> {
  // 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;
  }

}

您现在可以使用以下内容创建真实的表:

public class VersionTable extends Table<VersionTable.Column> {

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

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

请注意,这是一个非常简单的例子,但只需要做一些工作就可以很容易地将大量enum工作移到父类中。

此技术确实保留了使用泛型时获得的类型安全检查。

答案 2 :(得分:1)

枚举可以实现接口。我建议为这个任务提供一个合理的界面。让你的枚举实现接口,你的代码将继续正常工作。其他团队可以使用他们想要的任何接口实现(他们自己的枚举或其他)。 (注意,没有代码,很难做出非常明确的建议)。

答案 3 :(得分:0)

你可能不应该为此使用枚举,但如果你愿意,你可以在helper类中实现逻辑,或者在彼此扩展的类集合中实现逻辑,并使枚举成为一个薄的包装器:

public enum MyTaskEnum {
    A, B, C;

    private final TaskEnumHelper helper = new TaskEnumHelper();

    public void foo (int x, int y)
    {
        helper.foo (x, y);
    }
}

答案 4 :(得分:-1)

不是真的,枚举是语法糖,将它们暴露在它们被定义的代码之外会导致你直接进入一个非常不愉快的角落。

你最终会遇到一个共同定义的噩梦。

另一种常见的方法是将其作为整数传递并在任一侧进行转换,但这与常见定义没有太大区别,因为谁知道枚举类型A中的1是否在类型B中为1。

我们倾向于使用字符串。 所以我们将字符串转换为枚举值,在代码中使用它,然后在必要时将其转换回最后。像.Nets DescriptionAttribute这样的东西非常方便。

不能完全解决问题,但只要您同意某些说明名称的规则,例如:使用团队名称对它们进行前缀,您可以解决它。

你可以看一下传递类型和值,但是当你回到常见的定义场景时,这并没有多大帮助。