簡體   English   中英

如何在Kotlin中傳遞有界通配符類型參數?

[英]How to pass bounded wildcard type argument in Kotlin?

使用的類(在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() public Class<? extends WebPage> getPage()

這些都不起作用:

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

錯誤:沒有足夠的信息來推斷constructor Bookmarkable PageLink<T : Any!, C : 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))

這將是用Javaish發言的“假設正確”方式(只是意圖,但它不是真正的代碼),但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() ));

據我所知, BookmarkablePageLink(...)應該與Java中的new BookmarkablePageLink<>大致相同,因此這是“應該”工作的選項。 你試過的所有其他人都不應該出於不同的原因。

具有自己的類型參數的構造函數非常罕見(在看到這個問題之前我認為它們是非法的),因此在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中記下類型參數,因為第二個類型參數是捕獲的通配符

我正在從所有最好的評論中找到答案,因為那些看起來非常有價值。

問題的解決方法已經是一個良好的開端:

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

同樣公平的是@AlexeyRomanov的中間變量(或類似的中間函數):

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

對於通過Google發現此問題的所有人來說,也很有價值,可能是Kotlin與Java處理類型差異的簡短摘要,如Kotlin的文檔中所述

  • 在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完全相反的方法,我仍然很高興,我們只需要在極少數情況下需要解決方法。 ;-)

請試試

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM