我正在将Java中的一些类转换为kotlin,并且在尝试从接口继承时遇到编译错误:
平台声明冲突:以下声明具有相同的声明 JVM签名(getContentID()Ljava / lang / String;):
public open fun get-content-id():String? public open fun getContentId():String?
这是界面:
interface Media {
val contentId: String
val displayRunTime: String
val genres: List<String>
val programId: String
val runTime: String
val type: String
}
这是班级:
class Airing : Media {
override val contentId: String? = null
override val displayRunTime: String? = null
override val genres: List<String>? = null
override val programId: String? = null
override val runTime: String? = null
override val type: String? = null
override fun getContentId(): String? {
return contentId
}
我是kotlin的新手。
答案 0 :(得分:3)
您不需要声明override fun getContentId(): String?
,因为val contentId: String
界面中的Media
已被override val contentId: String?
覆盖。
您获得的错误意味着您声明的函数在JVM字节码中与已为contentId
属性生成的getter冲突(getter具有相同的签名)。
在Kotlin中,您应该直接使用属性contentId
,而在Java中,您可以使用生成的访问者getContentId()
和setContentId(...)
。
此外,Kotlin不允许您使用可为空的String
覆盖非空String?
属性,因为基接口的用户将期望该属性的非空值。您应该将覆盖的属性类型替换为String
,或者在界面中将它们设为String?
。
答案 1 :(得分:2)
主要问题是T?
类型包括T
和null
。反过来,T
是T?
的子集。所以你不能用它的超集类型覆盖T
属性,例如:
interface Source { val content: Any }
// v--- ERROR: `Any?` is not a subtype of `Any`
class Image(override val content:Any?) : Source
但是,您可以使用子集类型或子类型覆盖T?
属性,例如:
interface Source { val content: Any? }
// v--- `Any` is a subset of `Any?`
class Image(override val content:Any) : Source
// `String` is a subtype of `Any` & `Any?` includes `Any`
// v
class Text(override val content:String) : Source
然后您的代码应如下所示。但是,Kotlin是一个零安全系统,即使属性是可空的属性,也无法在不初始化属性的情况下定义属性:
class Airing : Media {
// v--- ERROR: the property isn't initialized
override val contentId: String
...
}
您应该在主构造函数中引入属性,让客户端代码在将来初始化它们,例如:
class Airing
constructor(
override val contentId: String,
override val displayRunTime: String,
override val genres: List<String>,
override val programId: String,
override val runTime: String,
override val type: String
) : Media
您还可以为属性提供一些默认值,例如:
class Airing : Media {
override val contentId: String = "<default>"
override val displayRunTime: String = "<default>"
override val genres: List<String> = emptyList()
override val programId: String = "<default>"
override val runTime: String = "<default>"
override val type: String = "<default>"
}
AND getContentId
功能会与getter
冲突,因此您应将其删除。
答案 2 :(得分:0)
声明为val
的变量与Java final
变量类似,是不可变的,因此您无法设置为Optional ?
您的变量声明应如下所示:
interface Media {
var contentId: String?
//...
}