2016-04-04 3 views
1

В настоящее время у меня есть несколько перечислений, определенных для нескольких классов. Все они похожи на показанный ниже:Создание абстрактного базового класса для обработки различных типов перечислений

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

Существует также метод, определенный в ApaMessage:

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

Проблема заключается в том, хотя там не много кода, я скоро 10-20 из этих перечислений. Я хотел бы создать абстрактный базовый класс, в котором метод HashMap и другие подобные методы могут быть частью. Базовый класс должен принимать перечисление ApaFields и другие перечисления и делать то, что делает getApaJsonFieldsAndValues. Проблема в том, как базовый класс может получить доступ к переданным значениям enum и внутренним полям, таким как jsonName, для выполнения цикла?

Я пробовал разные подходы, но главная проблема заключается в том, что базовый класс не может получить доступ к значениям. Есть ли способ обойти это? Альтернативно, есть ли лучший подход? Благодаря

EDIT:

В основном я хотел бы что-то подобное в базовом классе. Обратите внимание, что нижеследующее не компилируется.

общественного абстрактного класса 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     
     } 
    } 
} 

А затем вызвать базовый метод следующим образом, хотя и не уверен, если это правильно, где ApaFields это внутреннее перечисление определено выше.

ApaRequest(ApaFields.class, somestringmessage); 
+0

Покажите нам, что вы попробовали. –

+1

Если ваш пример не вводит в заблуждение, я думаю, вы не должны использовать внутренние перечисления. Я либо использовал бы определенную извне перечисление, содержащее все FIELDS, либо объявлял бы один FIELD как приватное поле для каждого класса. – Aaron

+1

Возможно, ваши перечисления должны реализовать общий интерфейс и работать только с этим интерфейсом в методе, возвращающем хэш-карту. – dumitru

ответ

0

Я столкнулся с чем-то похожим при попытке определить схему db, используя перечисления в виде столбцов в таблице. В конце концов я пошел по этому пути.

Определите базовый класс с достаточной общей подписью, чтобы обеспечить правильное построение перечисления.

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

} 

Теперь продлить это для каждой таблицы - вот простой 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)); 
    } 
} 

Теперь у вас есть все основные функциональные возможности базового класса и все подклассы нужно сделать, это реализовать интерфейс на enum.

Я понимаю, что это не касается вопроса о дублированном коде болибера в всех ваших перечислениях, но он перемещает alomst все это в другом месте.

+0

Спасибо за помощь, хотя один вопрос, как вы перебираете перемычку столбца в классе Table и получаете все значения в столбце? По сути, это моя большая проблема. То есть как вы это делаете (поле столбца: Column.values ​​()) {} Единственное, что доступно, это getEnumConstants(), а не фактические значения. –

+0

Это решение очень многословие. Вы можете использовать некоторый генератор кода, который будет анализировать некоторый формат XML или SQL для создания кода Java. –

+0

@SoucianceEqdamRashti - родительский класс «Таблица» заполняется локальным финальным столбцом 'Set ;' во время построения. Это можно просто повторить. Поскольку все они реализуют «Столбцы», их можно манипулировать обычным способом. – OldCurmudgeon

Смежные вопросы