已定义接口:
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>
答案 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。