Specify valid type types with parameter

Consider the following classes

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

Currently used as:

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

While this works, the problem is that createCommentQueryUnsafe() does not indicate a restriction on sortBy . Users can pass UserSortBy.NAME , although this does not make sense in this context.

I cannot figure out how to do this because simply adding <B extends SortBy> to the class signature means that I am losing the ability to limit the min parameter in the method. I cannot use something like <M, S extends B & SortBy<M>> as its compiler error . Other attempts using wildcard magic lead to significant complication and compiler errors. Moving the sort to the createCommentQuery() method would mean that 2 methods are required for each query, which is an insane amount of duplicated code

How can I write generalizations, so createCommentQuery() restricts the sortBy parameter sortBy only CommentSortBy , but CommentSortBy min limit it to the S parameter in the SortBy class?

+4
source share
1 answer

This is a really difficult problem for the reasons you indicated. I tried different approaches, but they were all defeated by the generic restriction that you specified . Ultimately, it seems to you that you need to make some design changes if you want the specified security to be of type.

Using the inheritance hierarchy of SortBy implementations for your generic type constraints seems to have led to this deadlock in particular. I tried to untie this restriction with a new type parameter on SortBy , which means the requested object itself, for example. Comment , User , etc. This is the design I came up with:

 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 )

+3
source

Source: https://habr.com/ru/post/1491420/


All Articles