2015-03-31 78 views
0

我試圖編寫一個interface我想要爲Datamodel-Classes實現。
爲此,我想在interface內部使用enum,所以我知道我需要稍後實施它。
例子:包含一個空Enum的Java接口

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 getter/setter的參數避免使用錯誤值的方法。

在此先感謝您的任何建議。

更新:

因此,這是對我工作:三個部分,其中包括一個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 2015-03-31 08:37:00

+0

我也考慮過這種情況,但只有在包含字段的模型類似時纔有效。客戶和供應商。儘管如果我使用String常量,仍然可以使用其他值的方法,例如:「setValue(」anyString「,」Testvalue「);」我想避免使用'enum'。 – KnusperPudding 2015-03-31 08:43:42

回答

3

接口字段隱含地爲staticfinal

你可以做的是有一個接口方法返回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'。但是,儘管如此,我仍然不能強迫這個人命名枚舉:「Field」,以及get和set方法:因此,他們將接受任何類型的枚舉,如下所示:public Object get(Enum field); – KnusperPudding 2015-03-31 09:04:37

+0

請記住,枚舉可以實現接口,這在這裏看起來很有用。 – chrylis 2015-03-31 09:10:54

+0

@chrylis:我意識到這一點,但我還沒有想出如何這可能對我的問題是有用的:(但我覺得我有另一個想法。 – KnusperPudding 2015-03-31 11:07:25

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

因爲類型擦除的枚舉映射需要的類。枚舉類上面也存儲爲字段,因爲一些靜態枚舉方法需要枚舉類。用於迭代,等等。

+0

我試過這個例子,我覺得解決方案是介於你和梅納斯之間的答案。 - 這幫助了很多。 – KnusperPudding 2015-03-31 10:42:26

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(「Name」),SurName(「SurName」)。我希望我可以避免創建新的類。 - 還是謝謝。 – KnusperPudding 2015-03-31 10:40:46