1

I have a code which was initially designed for just a single team where they were passing an enum [which stores list of tasks] to an api. This api then progates the use of this enum to many other classes.

Now i have a task where this code needs to be used by multiple teams and they can pass there own set of tasks in form of enums.

Given the current implementation i dont think it is feasible to support multiple teams which completely overhauling the code because enum's cannot extend other enums.

Is there any way to implement this without massive changes?

Lokesh
  • 7,810
  • 6
  • 48
  • 78
  • 9
    Code is worth 1024 words, a couple of short snippets demonstrating the current structure and the structure you think would be problematic would be very useful. – T.J. Crowder Feb 08 '13 at 12:44
  • Do different teams share similar tasks? Are they each unique with their own set? – cgatian Feb 08 '13 at 12:47
  • @cgatian: Tasks basically involve getting data from database, so yes functionally similar tasks. – Lokesh Feb 08 '13 at 13:49

4 Answers4

3

But... enums can implement interfaces, for example:

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

Now we can employ java generic kung fu to specify a generic parameter bounded to a suitable enum:

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

To use it:

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

FYI, as a curiosity of generics, you can alternatively use this bound to achieve the same thing:

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

Although I can find no practical difference in effect, I find it lacks the clarity and familiar pattern of the intersection bound above. For more on this see this question.

Community
  • 1
  • 1
Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • +1 - *As a curiosity of generics ...* interesting and strange. – OldCurmudgeon Feb 08 '13 at 13:42
  • @OldCurmudgeon I only recently realised it was possible, and even asked a [question](http://stackoverflow.com/questions/14122783/is-there-a-difference-between-these-generic-bounds) to confirm it is identical in effect - the consensus was "yes" – Bohemian Feb 08 '13 at 14:27
2

It is comparatively easy to make much of the work around enums generic.

Here's a severely cut-down example. It defines a generic database Table class that takes an enum Column as its defining type. The enum defines what columns are in the table. The defining type is an enum that also implements an interface which is a really useful trick.

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

}

You can now create your real table with something like:

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

Note that this is a truly trivial example but with a little work it is easy to move a lot of your enum work into the parent class.

This technique does retain the type-safety checks you get when using generics.

OldCurmudgeon
  • 64,482
  • 16
  • 119
  • 213
1

Enums can implement interfaces. I would recommend coming up with a reasonable interface for the task. make your enum implement the interface and your code will continue to work just fine. other teams can use whatever interface implementation they desire (their own enum or something else). (note, without code it's hard to make very explicit recommendations).

jtahlborn
  • 52,909
  • 5
  • 76
  • 118
0

You probably should not use enums for this, but if you want, you can implement logic in helper class, or set of classes that extend each other, and make enums a thin wrappers saround it:

public enum MyTaskEnum {
    A, B, C;

    private final TaskEnumHelper helper = new TaskEnumHelper();

    public void foo (int x, int y)
    {
        helper.foo (x, y);
    }
}
Mikhail Vladimirov
  • 13,572
  • 1
  • 38
  • 40