首页 文章

如何在Kotlin中传递有界通配符类型参数?

提问于
浏览
12

使用的类(在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 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))

这将是在Javaish-speak中做到这一点的方式(只是意图,但它不是真正的代码),但this isn't supported by Kotlin

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

我最好的解决方法就是这个,这很难看,但有效:

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

令人惊讶的是,这简直就是:

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

3 回答

  • 2

    我正在从所有最好的评论中找到答案,因为那些看起来非常有 Value .

    问题的解决方法已经是一个良好的开端:

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

    同样公平的是@AlexeyRomanov的中间变量(或类似的中间函数):

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

    对于通过Google发现此问题的所有人来说,也很有 Value 可能是Kotlin与Java处理类型差异的简短摘要,如Kotlin's documentation中所述:

    在Java中

    • 使用通配符处理呼叫站点(你不能使用,因为呼叫站点在Kotlin中)

    • 并且在Kotlin中,处理是在声明站点使用 inout 关键字(您不能使用,因为您的声明是Java)

    另外,call-site的Java构造函数只允许从类中指定类型参数,而在Kotlin中,构造函数调用有两个类型参数:一个来自类,另一个来自构造函数 . 所以在Java中,我们不得不说

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

    在Kotlin

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

    尽管两个都使用相同的参数调用相同的构造函数 .

    考虑到Kotlin为变体类型选择了一种与Java完全相反的方法,我仍然很高兴,我们只需要在极少数情况下需要解决方法 . ;-)

  • 3

    据我所知, BookmarkablePageLink(...) 应该大致相当于Java中的 new BookmarkablePageLink<> ,所以这是"should"工作的选项 . 你试过的所有其他人不应该出于不同的原因 .

    具有自己的类型参数的构造函数非常罕见(在看到这个问题之前我认为它们是非法的),因此在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中的类型参数,因为第二个类型参数是captured wildcard .

  • 6

    请试试

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

相关问题