2015-03-31 2 views
0

Я пытаюсь подготовить interface, который я хочу реализовать для классов Datamodel.
Для этого я хочу использовать enum внутри interface, поэтому я знаю, что мне нужно его реализовать позже.
Пример:Java-интерфейс, содержащий пустой Enum

public interface MyModelInterface { 

    public enum Field; 

    public Object get(Field field); 

    public void set(Field field, Object value); 
} 

Ожидаемое внедрение:

public class MyModel implements MyModelInterface { 


    public enum Field { 

     ID("id"), 
     Name1("Name1"), 
     Name2("Name2"); 

     private String field; 

     private Field(String field) { 
      this.field = field; 
     } 
    } 

    public Object get(Field field) { 
     //... 
    } 


    public void set(Field field, Object value){ 
     //... 
    } 

    public static void main(String[] args) { 
     MyModel myModel = new MyModel(); 
     System.out.println(myModel.get(MyModel.Field.ID)); 
     System.out.println(myModel.get(MyModel.Field.Name1)); 
    } 
} 

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

Я не хочу использовать String Параметры на приемнике/сеттере Способы избежать неправильных значений.

Заранее благодарим за любые предложения.

Update:

Так это то, что работает для меня: Разделение интерфейса/класса в трех частях, в том числе abstract class:

Интерфейс:

public interface MyModelInterface<E extends Enum<E>> { 

    public Object get(E field); 

    public void set(E field, Object value); 

} 

Аннотация Класс:

public abstract class MyAbstractModel<E extends Enum<E>> implements MyModelInterface<E>{ 

    protected final EnumMap<E, Object> fields; 

    public MyAbstractModel(Class<E> enumKlazz) { 
     fields = new EnumMap<>(enumKlazz); 
    } 

    @Override 
    public Object get(E field) { 
     return fields.get(field); 
    } 

    @Override 
    public void set(E field, Object value) { 
     this.fields.put(field, value); 
    } 
} 

Класс (где я фактически архивирую свою цель):

public class MyModel extends MyAbstractModel<MyModel.Field> { 

    public MyModel() { 
     super(MyModel.Field.class); 
    } 

    public enum Field { 

     ID("ID"), 
     Name1("NAME1"), 
     Name2("NAME2"), 
     Age("AGE"), 
     ; 
     private final String field; 

     private Field(String field) { 
      this.field = field; 
     } 
     public String getName() { 
      return field; 
     } 
    } 

    public static void main(String[] args) { 
     MyModel myModel = new MyModel(); 
     System.out.println(myModel.get(Field.Name1)); 
    } 
} 
+0

Возможно, создавая Класс 'abstract' с несколькими константами может сработать для вас? – Dragondraikk

+0

Я тоже думал об этом, но он работал бы только в том случае, если модель, содержащая поля, подобна, например. клиента и поставщика. хотя, если я использую String константы, все еще можно использовать методы с другими значениями, например: setValue («anyString», «Testvalue»); который я хочу избежать использования 'enum'. – KnusperPudding

ответ

3

Поля интерфейса static и final неявно.

Что вы можете сделать, это получить метод интерфейса, возвращающий Enum<?>, и ваши классы, реализующие его.

Например:

interface Foo { 
    public Enum<?> getEnum(); 
} 
class Bar implements Foo { 
    enum Blah { 
     INSTANCE; 
    } 

    public Enum<?> getEnum() { 
     return Blah.INSTANCE; 
    } 
} 

Редактировать

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

Этот пример является самодостаточным в классе Main.

public class Main { 

    public static void main(String[] args) { 
     System.out.println(new Bar().getEnumField().name()); 
    } 
    static interface IHasEnum { 
     public Enum<? extends IMyEnum> getEnumField(); 
    } 
    static interface IMyEnum { 
     public Enum<? extends IMyEnum> getField(); 
    } 
    static class Bar implements IHasEnum { 
     enum Blah implements IMyEnum { 
      DEFAULT_INSTANCE, 
      THE_FIELD; 
      public Enum<? extends IMyEnum> getField() { 
       return THE_FIELD; 
      } 
     } 
     public Enum<? extends IMyEnum> getEnumField() { 
      return Blah.DEFAULT_INSTANCE.getField(); 
     } 

    } 
} 

Выход

THE_FIELD 

Примечание

Хитрость здесь, чтобы добавить экземпляр "по умолчанию" для перечисления (DEFAULT_INSTANCE), поэтому метод getField является метод экземпляра , следовательно, переопределяя значение, указанное в интерфейсе IMyEnum.

Снова не совсем уверен, что это касается вашей проблемы.

+0

Спасибо, это довольно хороший подход. Таким образом, я могу по крайней мере заставить человека, который его реализует, использовать «enum». но, тем не менее, я все еще не могу заставить человека назвать перечисление: «Поле», а также для методов get и set: для этого они будут принимать любой вид перечисления, выглядящий следующим образом: public Object get (Enum ); – KnusperPudding

+0

И помните, что перечисления могут реализовывать интерфейсы, которые здесь кажутся полезными. – chrylis

+0

@chrylis: Я знаю об этом, но я не понял, как это может быть полезно для моей проблемы :(но у меня есть другая идея. – KnusperPudding

1

То, что вы описываете это EnumMap<E, T> - который функционирует как массив, с той же get -

public class MyModelBase<E extends Enum<E>> { 
    private final Class<E> enumKlazz; 
    private final EnumMap<E, Object> fields; 

    public MyModelBase(Class<E> enumKlazz) { 
     this.enumKlazz = enumKlazz; 
     fields = new EnumMpa<>(enumKlazz); 
    } 

    public Object get(E field) { 
     return fields.get(field); 
    } 

    public void set(E field, Object value) { 
     fields.put(field, value); 
    } 
} 

enum UserField { id, surname, name, age }; 
MyModelBase<UserField> userModel = new MyModelBase<>(UserField.class); 
userModel.set(UserField.surname, "X"); 

Из-за типа стирания карты нужно перечисление класса. Над классом enum также сохраняется как поле, так как некоторые статические методы Enum нуждаются в классе enum. Для итерации и т. Д.

+0

Я попробовал пример, и я считаю, что решение находится где-то между вашим и Менасом. - Это помогло много. – KnusperPudding

0

Java-дженерики будут лучшим решением. Предположим, вы не знаете содержание поля, как упомянуто.

Создать общий интерфейс, как это:

public interface MyModelInterface<T> { 
    public T get(); 
} 

Затем создать поле класса, как это:

public class Field { 
    private String id; 
    private String name1; 
    private String name2; 

    public String getId() { 
     return id; 
    } 

    public void setId(String id) { 
     this.id = id; 
    } 

    public String getName1() { 
     return name1; 
    } 

    public void setName1(String name1) { 
     this.name1 = name1; 
    } 

    public String getName2() { 
     return name2; 
    } 

    public void setName2(String name2) { 
     this.name2 = name2; 
    } 
} 

, а затем ваш класс модель будет выглядеть

public class MyModel implements MyModelInterface<Field> { 
    @Override 
    public Field get() { 
     Field field = new Field(); 
     field.setId("ID"); 
     field.setName1("Name1"); 
     field.setName2("Name2"); 

     return field; 
    } 

    public static void main(String[] args) { 
     MyModel myModel = new MyModel(); 
     System.out.println(myModel.get().getId()); 
     System.out.println(myModel.get().getName1()); 
     System.out.println(myModel.get().getName2()); 
    } 
} 
+1

Идея довольно хорошая, но проблема в том, что вы хотите перечислить: есть довольно много таблиц с большим количеством полей. Я также опасаюсь проблемы производительности со всеми новыми экземплярами. Перечисления должны выглядеть довольно просто, как ID («ID»), Name («Имя»), SurName («SurName»). Я надеялся, что смогу избежать создания новых классов. - Еще спасибо. – KnusperPudding

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