2016-04-04 10 views
1

Derzeit habe ich mehrere Enums über mehrere Klassen definiert. Sie sehen alle ähnlich dem unten dargestellt:Erstellen einer abstrakten Basisklasse für verschiedene Arten von Enums

public class ApaMessage { 
    private String apaMessage; 
    private final int FIXED_LENGTH_SIZE=39; 


    public enum ApaFields { 
    FIELD1(ApaUtils.ApaFieldTypes.POSITION_BASED, null, "field1", 2, 3, false, false), 
    private final ApaUtils.ApaFieldTypes type; 
    private final String ApaName; 
    private final String jsonName; 
    private final int start; 
    private final int finish; 
    private boolean required = false; 
    private boolean withDelimiter = false; 

ApaFields(ApaUtils.ApaFieldTypes type, String ApaName, String jsonName, int start, int finish, boolean required, boolean withDelimiter) { 
     this.type = type; 
     this.ApaName = ApaName; 
     this.jsonName = jsonName; 
     this.start = start; 
     this.finish = finish; 
     this.required = required; 
     this.withDelimiter = withDelimiter; 
    } 
    } 

Es gibt auch ein Verfahren, in ApaMessage definiert:

private HashMap<String,Object> getApaJsonFieldsAndValues() { 
    HashMap<String, Object> jsonApaData = new HashMap<String, Object>(); 
    for (ApaFields field : ApaFields.values()) { 
     jsonApaData.put(field.jsonName, getApaFieldValue(field)); 
    } 
    return jsonApaData; 
    } 

Das Problem ist, obwohl es nicht viel Code, ich werde bald 10-20 dieser enums. Ich möchte eine abstrakte Basisklasse erstellen, in die die HashMap-Methode und andere ähnliche Methoden eingebunden werden können. Die Basisklasse sollte eine ApaFields-Enumeration und andere Enums akzeptieren und tun, was getApaJsonFieldsAndValues ​​tut. Das Problem ist, wie kann die Basisklasse auf die übergebenen enum-Werte und die internen Felder wie jsonName zugreifen, um die Schleife auszuführen?

Ich habe verschiedene Ansätze ausprobiert, aber das Hauptproblem ist, dass die Basisklasse scheinbar nicht auf die Werte zugreifen kann. Gibt es einen Weg dazu? Oder gibt es einen besseren Ansatz? Dank

EDIT:

Grundsätzlich würde ich so etwas wie dies in der Basisklasse mag. Beachten Sie, dass das Folgende nicht kompiliert wird.

public abstract class ApaRequestMessage {

private Class<? extends Enum<?>> apaRequestMessageFields; 
    private String apaMessage; 
    public <T extends Enum<T>> void ApaRequest(Object apaRequestFields, String apaMessage) { 

     apaRequestMessageFields = (Class<? extends Enum<?>>) apaRequestFields; 
     this.apaMessage = apaMessage;  
     for (Field field: apaRequestMessageFields.values()) { 
      //this doesn't work because it cannot access the values of apaRequestMessageFields     
     } 
    } 
} 

Und dann die Basis-Methode aufrufen, wie folgt, wenn auch nicht sicher, ob dies richtig ist, wo ApaFields die innere Enum oben definiert ist.

+0

Zeigen Sie uns, was Sie versucht haben. –

+1

Wenn Ihr Beispiel nicht irreführend ist, sollten Sie keine inneren Aufzählungen verwenden. Ich würde entweder eine extern definierte Enumeration verwenden, die alle FIELDS enthält, oder ein einzelnes FIELD als privates Feld für jede Klasse deklarieren. – Aaron

+1

Vielleicht sollten Ihre Enums eine gemeinsame Schnittstelle implementieren und Sie arbeiten nur mit dieser Schnittstelle in der Methode, die die Hash-Map zurückgibt. – dumitru

Antwort

0

Ich stieß auf etwas Ähnliches beim Versuch, ein Datenbankschema mit enums als Spalten in der Tabelle zu definieren. Ich habe diesen Weg schließlich genommen.

Definieren Sie eine Basisklasse mit ausreichender generischer Signatur, um sicherzustellen, dass die Enumeration ordnungsgemäß erstellt wird.

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

} 

Nun ist diese für jede Tabelle erweitern - hier ist ein einfaches VersionTable:

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

Jetzt haben Sie alle der Kernfunktionalität in der Basisklasse und alle Unterklassen tun müssen, ist zu implementieren die Schnittstelle auf der enum.

Ich weiß, dass dies nicht das Problem der doppelten bolisteller-Code in allen Ihren enums, aber es bewegt sich alomst alles andere woanders.

+0

Danke für die Hilfe, eine Frage, wie schwirren Sie über die Spaltenaufzählung in der Tabellenklasse und erhalten Sie alle Werte in Spalte? Im Wesentlichen ist das mein großes Problem. I.e. Wie geht es für (Spaltenfeld: Column.values ​​()) {} Das einzige, was zugänglich ist, ist getEnumConstants() und nicht die tatsächlichen Werte. –

+0

Diese Lösung ist sehr ausführlich. Sie könnten einen Codegenerator verwenden, der ein XML- oder SQL-Format parst, um Java-Code zu erzeugen. –

+0

@SoucianceEqdamRashti - Die Elternklasse 'Table' wird mit einem lokalen finalen' Set columns; 'zur Konstruktionszeit gefüllt. Dies kann einfach wiederholt werden. Da sie alle "Spalten" implementieren, können sie auf eine gemeinsame Art und Weise manipuliert werden. – OldCurmudgeon

Verwandte Themen