簡體   English   中英

Kotlin:參數化類型的構造函數引用給出了編譯錯誤

[英]Kotlin: constructor reference for a parameterized type gives a compilation error

我試圖用Kotlin編寫類似於以下Java代碼的內容:

interface Provider {
}

class ProviderImpl1 implements Provider {
}

class ProviderImpl2 implements Provider {
}

enum Providers {
    ONE(ProviderImpl1::new),
    TWO(ProviderImpl2::new);

    private final Supplier<Provider> supplier;

    Providers(Supplier<Provider> supplier) {
        this.supplier = supplier;
    }

    public Provider provider() {
        return supplier.get();
    }
}

此代碼編譯和正常工作: Providers.ONE產生的一個實例ProviderImpl1Providers.TWO給出的實例ProviderImpl2

這是我在Kotlin可以實現的目標:

interface Provider {
}

class ProviderImpl1 : Provider {
}

class ProviderImpl2: Provider {
}

enum class Providers(private val factory: Supplier<Provider>) {
    ONE(Supplier{ ProviderImpl1() }),
    TWO(Supplier{ ProviderImpl2() });

    fun provider(): Provider = factory.get()
}

它可以工作,但是在Java中,我可以在枚舉構造函數中使用構造函數引用。 當我嘗試在科特林做同樣的事情時

ONE( ::ProviderImpl1 ),

我收到以下編譯錯誤:

類型不匹配:推斷的類型為KFunction0,但應為供應商

沒有顯式類型的lambda也不起作用:

ONE( ::ProviderImpl1 )

類型不匹配:推斷的類型為()-> ProviderImpl1,但是期望供應商

問題是:Kotlin規范是否禁止這種情況(如果是,是為什么,正如Java似乎要解決的那樣),或者這僅僅是當前Kotlin編譯器的暫時缺陷?

我的build.gradle具有以下內容

plugins {
    id 'org.jetbrains.kotlin.jvm' version '1.2.61'
}

Idea在項目設置中將Kotlin語言版本顯示為1.2。

如果將Supplier更改為lambda,則可以在Kotlin中很好地實現...

interface Provider
class ProviderImpl1 : Provider
class ProviderImpl2 : Provider

enum class Providers(private val supplier: () -> Provider) {
    ONE({ ProviderImpl1() }),
    TWO({ ProviderImpl2() });

    fun provider(): Provider = supplier.invoke()
}

此處的更改是傳遞返回Provider實例的函數(本質上是Suppiler功能)。 很好,因為如果將來您的Provider實現在構造時需要某種配置,則此lambda可以處理該配置。

如果您的提供程序是無狀態的,則可以通過將Providers.provider()更改為val ,在該方法中,每個枚舉類型僅創建一次。

您可以像編譯錯誤建議那樣使用kotlin.reflect.KFunction0而不是java.util.function.Supplier ,然后可以使用方法引用。

例:

import kotlin.reflect.KFunction0

interface Provider {
}

class ProviderImpl1 : Provider {
}

class ProviderImpl2: Provider {
}

enum class Providers(private val factory: KFunction0<Provider>) {
    ONE(::ProviderImpl1),
    TWO(::ProviderImpl2);

    fun provider(): Provider = factory.call()
}

在這種情況下,錯誤消息表明它期望使用java.util.function.Supplier以外的接口kotlin.reflect.KFunction0 ,因此不禁止在此構造方法中使用方法引用。 您可以使用它,只需要使用預期的接口即可。

暫無
暫無

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

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