2010-10-26 93 views
0

我有泛型結構,我需要使用各種泛型類型的屬性進行搜索。替代泛型類型的字段

我們認爲以下實現的:

public class Person { 
    private int id; 
    private String name; 
    // + getters & setters 
} 

現在我有我的自定義的數據結構和它的一個方法是這樣的:

public T search(T data) { ... } 

這當然是無稽之談。我真正需要的代碼是一樣的東西:

Person p = structure.search(12); // person's id 

Person p = structure.search("Chuck N."); // person's name 
在pseudoJava(:))

因此,代碼會是這樣的:

public T search(T.field key) 

這ISN」當然可能:(但是,如何處理這種情況?重點是:我不想強制客戶端的類(如Person)實現我自己的接口或擴展我自己的類。是否有任何解決方法?

回答

2

看起來你想要某種中介的戰略目標,即提取值,比較值,或許提供了一個哈希碼或比較功能。

是這樣的:

interface Matcher<T> { 
    boolean matches(T obj); 
} 

或方法,例如:

boolean matches(T obj, V value); 

    V get(T obj); 

    int hash(T obj); 

    int compare(T a, T b); 

使用是與當前Java語法稍微詳細(可以針對JDK 8改變)。

你最終的東西是這樣的:

Person p = structure.search(
    new Matcher<Person>() { public boolean matches(Person person) { 
     return person.getID() == 12; 
    }) 
); 

或:

Person p = structure.search(
    new Matcher<Person,Integer>() { 
     public boolean matches(Person person, Integer id) { 
      return person.getID() == id; 
     } 
    ), 
    12 
); 

在JDK8,或許是這樣的:

Person p = structure.search(
    { Person person -> person.getID() == 12 } 
); 

或:

Person p = structure.search(
    { Person person, Integer id -> person.getID() == id }, 
    12 
); 

或:

Person p = structure.search(
    { Person person -> person.getID() }, 
    12 
); 

或:

Person p = structure.search(
    Person#getID, 12 
); 
+0

但Person類被強制執行Matcher,是否正確? – Xorty 2010-10-26 13:08:09

+0

不,我會再添加一些。 – 2010-10-26 13:16:51

+0

請這樣做:) – Xorty 2010-10-26 13:22:02

2

您可以通過添加Class參數使搜索的簽名包含類型參數。舉個例子:

//replace 'id' with whatever your identifier types are 
public <T> T search(int id, Class<T> entityClass) { ... } 

客戶將不得不使用的方法類似

Person p = foo.search(123, Person.class); 
NotAPerson n = foo.search(234, NotAPerson.class); 

它可能看起來有點醜必須包括類,但是當你真正想的事情 - 沒有按」客戶總是知道它在搜索什麼?並且search()背後的代碼不需要知道要搜索哪種類型 - 如果您具有由不同類型共享的ID,該怎麼辦?

如果你的ID是一致的類型的不是,你可以在簽名更改爲

public <T> T search(Serializable id, Class<T> entityClass) { ... } 
+0

我真的不知道,「id」是什麼。它可能是int,string,date,無論如何:>我只知道它的T屬性。這有幫助嗎? :/ – Xorty 2010-10-26 12:45:41

+0

那麼,你在尋找什麼 - T的「標識符」,或T的任何任意屬性?這個例子其實並不重要,第一個參數可以用'search()'方法解釋爲任何東西 - 我的答案的實際部分是添加'Class '作爲參數。 – 2010-10-26 12:47:05

+0

你是否介意編輯你的答案,例如我寫的?我不太明白你的觀點。我有同質結構。我知道,這種結構中只有Ts。在我們的例子中 - 我有充滿人的結構。沒有別的東西到達那裏我不知道的是我應該在我的搜索方法中指定什麼「關鍵」。換句話說,你會用什麼來代替你的「int id」?你如何訪問T的領域? – Xorty 2010-10-26 12:56:48

0

我建議你使用可比接口。

Person p = structure.searchUnique(new FieldFilter(「id」,12)); Person搜索id爲12 Person [] p = structure.searchAll(new FieldFilter(「name」,「John」)); //搜索名爲John

而且我們可以實現過濾器,可以搜索超過目標類的所有可用字段人:

人[P = structure.searchAll(新FieldFilter(「約翰」)) ; //搜索所有Johns

如何實施?這裏有一些提示。

首先什麼是「結構」?它是一個包含收集的封裝,將來可能包含一些索引功能。這個類應該像

構造函數結構(集合數據);

其在給定集合搜索方法進行迭代,並調用compateTo()FieldFilter的方法實現可比:對(T ELEM:集合)

{ 如果(filter.compareTo(ELEM)){ result.add (ELEM); } } 返回結果;

的FieldFilter應該是這樣的:

公共類FieldFilter實現可比{ 私人字符串字段名; private V fieldValue; public FieldFilter(String fieldName,V fieldValue){ this.fieldName = fieldName; this.fieldValue = fieldValue; } public boolean compareTo(T elem){field} = elem.getClass()。getField(fieldName); field.setAccessible(true); return field.getValue()。equals(fieldValue); } }

請注意,代碼是直接以答案形式編寫的,從未編譯過,因此無法按原樣使用。但我希望它能描述這個想法。

+0

我也在考慮使用反射,但我認爲這不是最優的。由於程序員 - 作爲API客戶端 - 不太瞭解java.lang.reflect,它也帶來了潛在的問題(我們都知道它是哪個)。 – Xorty 2010-10-26 13:47:46

0

如果要通過搜索類型和傳遞給search()方法的參數類型之間的泛型實施映射,必須在某處指定此地址。如果沒有至少一個客戶端類的通用標記接口,我認爲沒有辦法做到這一點。

像這樣的事情,例如將工作:

public interface Searchable<T> { } 

public class Person implements Searchable<String> { 
    // ... 
} 

public <T extends Searchable<K>, K> T search(K key) { 
    // ... 
} 

所以,現在的編譯器將允許:

Person p = search("John Doe"); 

但不是:

Person p = search(5); 

如果連一個標記接口不一個選項,恐怕最好的選擇是使用基於參數類型的特定搜索方法,如:

public <T> T searchByInt(int key) { 
    // ... 
} 

public <T> T searchByString(String key) { 
    // ... 
} 

但當然,這將意味着無效的情況下,像

Person p = searchByInt(5); 

不會在編譯時被捕獲,而是需要在運行時檢查來代替。

+0

yayx,這是好的和可讀的,但我不能現在重新實現原始類:)我感謝您的建議,但匹配模式(湯姆霍金寫道)現在更適合我。 – Xorty 2010-10-26 13:43:26

+0

好的;我以爲你正在尋找一個像搜索(K)這樣的方法簽名,K以某種方式映射到Person類。但是,如果傳遞匿名接口實現以及一些匹配邏輯也可以,那麼是的,我同意湯姆霍金的解決方案可能是最適合你的解決方案。 – 2010-10-26 14:13:25