为什么一个会出现“平台声明冲突”,而另一个很好呢?

时间:2018-10-08 19:55:06

标签: kotlin

已定义接口:

interface IData {

    fun getHash() : Int
    fun getUUID(): UUID

    ......
}

尝试为接口创建对象。 fun getUUID(): UUID很好,但是fun getHash() : Int出现如下错误。

可能是什么问题?为什么它们不同?

fun buidlDataList () : ArrayList<IData> {

    val dataList = ArrayList<IData>(0)

    dataList.add(object : IData {

        val hash: Int by lazy { dataFetchers.size+System.currentTimeMillis().toInt() } //<=== get error
        override fun getHash(): Int {                                                  //<=== get the same error
            return hash
        }

        val uuid: UUID by lazy { UUID.randomUUID() }
        override fun getUUID(): UUID {
            return uuid
        }
        ......
    }
}


Platform declaration clash:  The following declarations have the same JVM signature(getHash() I):
    * public final fun <get-hash>(): int  defined in com.data. buidlDataList <no name provided>
    * public open fun getHash(): int defined in defined in com.data. buidlDataList <no name provided>

1 个答案:

答案 0 :(得分:3)

变量创建了自己的吸气剂,但您也明确定义了它们。声明var或val时,它们通常具有自动生成的自己的getter 1 。如果您不创建自定义获取器,则不提供私有val或var。

但是在所有其他情况下,这是

val x: Int = TODO()

产生一个吸气剂 1

在您的情况下,建议您直接在界面中使用val。您会看到,生成的getter与您显式声明的getHash方法具有相同的名称。吸气剂也不会覆盖方法(除非您使用@Jvm注释之一对其进行注释,而且我不记得是哪个,但无论如何您实际上并不需要这些)。

因此,您将界面更改为:

interface IData {
    val hash: Int
    val uuid: UUID
}

然后删除覆盖对象中的吸气剂,并将override添加到val中:

dataList.add(object : IData {
    override val hash: Int by lazy { dataFetchers.size+System.currentTimeMillis().toInt() }
    override val uuid: UUID by lazy { UUID.randomUUID() }
}

第一个接口实际上等效于使用get和set方法声明一个接口。如果从Java覆盖它,它将要求您覆盖getHash()getUid(),并且您需要在本地声明该字段。 Kotlin的工作方式有所不同,因为它会自动生成setter。

并且由于您可以在接口中声明变量而不会弄乱Java互操作性,因此我强烈建议您在@ Jvm *批注中使用它(主要是因为这样可以更轻松地理解代码,尽管这是个人喜好)。


此外,如果您反编译Kotlin字节码,则会看到带有变量的接口将编译为:

public interface IData {
   int getHash();

   @NotNull
   UUID getUuid();
}

因此它与您最初使用的相同,只是在子类中没有因为变量名冲突而引起冲突。


而且只有一个发生冲突的原因是,正如您在界面中看到的那样,val uuid创建了一个名为getUuid的吸气剂,而您的界面声明了getUUID。 Java和Kotlin中的方法区分大小写,这就是为什么它们不会冲突的原因。如果将变量重命名为大写UUID,则也会发生冲突。

1:假设变量/常量不在方法中。顶级变量,接口中的变量,枚举,类,对象和伴随对象均会生成getter / setter,但如果在方法内声明变量,则在适用的地方自然不会有getter和setter。