2013-07-15 36 views
4

考慮下面的類指定與參數

public interface SortBy<S> { 
} 

public class CommentSortBy<S> implements SortBy<S> { 
    public static CommentSortBy<Date> CREATION = new CommentSortBy<Date>(); 
    public static CommentSortBy<Integer> VOTES = new CommentSortBy<Integer>(); 
} 

public class SomeQueryUnsafe { 
    public <M, S extends SortBy<M>> void setSort(S sortBy, M min) { 
     //Set relevant values 
    } 
} 

這有效泛型目前用作:

public SomeQueryUnsafe createCommentQueryUnsafe() { 
    return new SomeQueryUnsafe(); 
} 

public void test() { 
    createCommentQueryUnsafe().setSort(CommentSortBy.CREATION, new Date()); 
} 

雖然這工作,問題是createCommentQueryUnsafe()不會對sortBy指定限制。用戶可以自由地通過UserSortBy.NAME即使這在這方面並沒有什麼意義

因爲剛加入<B extends SortBy>到類簽名意味着我失去限制min參數的能力,我無法弄清楚如何做到寫這雖然在該方法中。我不能使用像<M, S extends B & SortBy<M>>那樣的its a compiler error。其他使用通配符的嘗試只會導致更多的複雜性和編譯錯誤。移動分揀到createCommentQuery()方法將意味着每一個查詢需要2種方法,這是重複的代碼一個瘋狂的金額

我怎麼可能寫的仿製藥,從而createCommentQuery()限制sortBy參數只是CommentSortBy同時還具有min限於SortBy類中的S參數?

回答

3

這確實是一個棘手的問題,因爲你指出的原因。我嘗試了各種方法,但他們都被generics limitation you cited擊敗。最終,如果您希望指定的類型安全,您似乎需要進行一些設計更改。

對泛型類型限制使用SortBy實現的繼承層次似乎導致了這種僵局。我嘗試將該限制解耦爲SortBy上的一個新類型參數,該參數表示查詢對象本身,例如, CommentUser等,這是我想出了設計:

static class Comment { } 

static class User { } 

interface SortBy<T, M> { } 

static class CommentSortBy<M> implements SortBy<Comment, M> { 

    static final CommentSortBy<Date> CREATION = new CommentSortBy<Date>(); 
    static final CommentSortBy<Integer> VOTES = new CommentSortBy<Integer>(); 
} 

static class UserSortBy<M> implements SortBy<User, M> { 

    static final UserSortBy<String> NAME = new UserSortBy<String>(); 
} 

static class Query<T> { 

    public <M> void setSort(SortBy<T, M> sortBy, M min) { 
     //Set relevant values 
    } 
} 

public static void main(String[] args) { 

    new Query<Comment>().setSort(CommentSortBy.CREATION, new Date()); 
    new Query<Comment>().setSort(UserSortBy.NAME, "Joe"); //compiler error 
} 

ideone

+0

首先,有許多 「創造」 的方法:'createUserQuery()','createCommentQuery()',等等。每個都需要創建一個查詢,以將sortBy值限制爲其特定的上下文。你所做的只是讓create方法返回通用版本,它仍然讓'createCommentQuery()'接受'UserSortBy.NAME',這是一個完全無效的註釋值。 – TheLQ

+0

理想情況下'createCommentQuery()'會返回類似'SomeQuery '這意味着sortBy只接受'sortBy(CommentSortBy.CREATION,someDate)'和'sortBy(CommentSortBy.VOTES,5L)',但不會'sortBy (UserSortBy.NAME,「Sam」)' – TheLQ

+0

@TheLQ這是有道理的,但不會調用'SomeQueryUnsafe。,Object> create()'來接近施加該限制嗎? (暫時忽略不靈活的'M'參數)。 –