Как передать аргумент ограниченного подстановочного знака в Kotlin? - PullRequest
0 голосов
/ 19 мая 2018

Используемый класс (в Java, сторонний API, неизменяемый):

public class BookmarkablePageLink<T> extends Link<T> {

    public <C extends Page> BookmarkablePageLink(final String id, final Class<C> pageClass)

И теперь я хочу вызвать его из Kotlin:

item.queue(BookmarkablePageLink("link", bookmark.page))

bookmark.page - этов Java, и это: public Class<? extends WebPage> getPage()

Ни одна из этих работ:

item.queue(BookmarkablePageLink("link", bookmark.page))

Ошибка: недостаточно информации для вывода параметра T в constructor Bookmarkable PageLink<T : Any!, C : Page!>(...)

item.queue(BookmarkablePageLink<>("link", bookmark.page))

item.queue(BookmarkablePageLink<Any>("link", bookmark.page))

item.queue(BookmarkablePageLink<Any, *>("link", bookmark.page))

item.queue(BookmarkablePageLink<Any, WebPage>("link", bookmark.page))

item.queue(BookmarkablePageLink<Any, in WebPage>("link", bookmark.page))

item.queue(BookmarkablePageLink<Any, out WebPage>("link", bookmark.page))

item.queue(BookmarkablePageLink<Any, T : WebPage>("link", bookmark.page))

Это был бы "гипотетически правильный" способ сделать это на языке, говорящем на Java (просто намерение, но это не настоящий код), но это не такподдерживается Kotlin :

item.queue(BookmarkablePageLink<Any, ? extends WebPage>("link", bookmark.page))

Мой лучший обходной путь - это уродливо, но работает:

item.queue(BookmarkablePageLink<Any, WebPage>("link", bookmark.page as Class<WebPage>))

Удивительно, но на Java это было просто:

item.queue(new BookmarkablePageLink<>("link", bookmark.getPage() ));

Ответы [ 3 ]

0 голосов
/ 22 мая 2018

Насколько я понимаю, BookmarkablePageLink(...) должно быть приблизительно эквивалентно new BookmarkablePageLink<> в Java, поэтому этот вариант "должен" работать.Все остальные, которые вы пробовали, не должны, каждый по разным причинам.

Конструкторы, которые имеют свои собственные параметры типа, очень редки (до того, как я увидел этот вопрос, я подумал, что они недопустимы), поэтому их можно пропустить где-нибудь в компиляторе Kotlin.Возможный обходной путь - вместо этого сделать его функцией:

fun <T, C : Page> makeBookmarkablePageLink(id: String, clazz: Class<C>): BookmarkablePageLink<T> = 
    BookmarkablePageLink<T, C>(id, clazz)

, а затем

item.queue(makeBookmarkablePageLink("link", bookmark.page))

Я также отмечу, что я почти уверен

«правильный» способ сделать это на языке Java

на самом деле неверен;и на самом деле вы не можете записать параметры типа в Java явно, потому что вторым параметром типа является захваченный подстановочный знак .

0 голосов
/ 27 мая 2018

Я создаю ответ из всех лучших комментариев, потому что они уже кажутся очень ценными.

Обход из вопроса уже хорошее начало:

BookmarkablePageLink<Any, WebPage>("link", bookmark.page as Class<WebPage>)

Также справедливо @ AlexeyRomanov'sпромежуточная переменная (или аналогичная промежуточная функция):

val link: BookmarkablePageLink<Any> = BookmarkablePageLink("link", bookmark.page)

Также ценным для всех, кто находит этот вопрос через Google, может быть краткое изложение обработки дисперсии типов в Kotlin vs Java, как описано в Kotlin'sдокументация :

  • в Java обработка выполняется на сайте вызова с использованием групповых символов (которые нельзя использовать, поскольку сайт вызова находится в Kotlin)
  • и в Kotlinобработка выполняется на сайте объявления с использованием ключевых слов in и out (которые вы не можете использовать, потому что ваше объявление находится на Java)

Кроме того, конструкторы Java на сайте вызова позволяют толькоукажите аргументы типа из класса, в то время как в Kotlin вызов конструктора имеет два аргумента типа: один из класса и другой из конструктора.Поэтому в Java мы должны сказать

new BookmarkablePageLink<T>("something", Page.class)

и в Kotlin

BookmarkablePageLink<T, Page>("something", Page::class.java)

, несмотря на то, что оба они вызывают один и тот же конструктор с одинаковыми аргументами.

Учитывая, что Kotlin выбралподход к вариантным типам, который является полной противоположностью Java, я все еще счастлив, что обходные пути нам нужны лишь в очень немногих случаях.; -)

0 голосов
/ 21 мая 2018

Пожалуйста, попробуйте

item.queue(BookmarkablePageLink<Any, WebPage>("link", bookmark.page)) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...