繁体   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