简体   繁体   English

在Kotlin中使用Interface时获取平台声明冲突

[英]Getting Platform declaration clash when using Interface in kotlin

I'm converting some classes in Java to kotlin and I'm running into compile errors when trying to inherit from an interface: 我将Java中的某些类转换为kotlin,并且尝试从接口继承时遇到编译错误:

Platform declaration clash: The following declarations have the same JVM signature (getContentID()Ljava/lang/String;): 平台声明冲突:以下声明具有相同的JVM签名(getContentID()Ljava / lang / String;):

public open fun get-content-id (): String? public open fun get-content-id():字符串? public open fun getContentId(): String? public open fun getContentId():字符串?

Here is the interface: 这是界面:

interface Media {
  val contentId: String

  val displayRunTime: String

  val genres: List<String>

  val programId: String

  val runTime: String

  val type: String
}

here is the class: 这是课程:

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
  }

I'm super new to kotlin. 我是科特林的新手。

You don't need to declare override fun getContentId(): String? 您不需要声明override fun getContentId(): String? , because the val contentId: String from the Media interface is already overridden by override val contentId: String? ,因为Media接口中的val contentId: String已被override val contentId: String? .

The error that you get means that the function you declare clashes in the JVM bytecode with the getter that is already generated for the contentId property (the getter has the same signature). 您得到的错误意味着您声明的函数在JVM字节码中与已经为contentId属性生成的getter发生冲突(getter具有相同的签名)。

In Kotlin, you should work with the property contentId directly, whereas in Java you can use the generated accessors getContentId() and setContentId(...) . 在Kotlin中,应该直接使用contentId属性,而在Java中,可以使用生成的访问器getContentId()setContentId(...)

Also, Kotlin does not allow you to override a not-null String property with a nullable String? 另外,Kotlin不允许您使用可为null的String覆盖not-null的String属性String? one, because the users of the base interface will expect a not-null value from the property. 一个,因为基本接口的用户将期望该属性的值不为null。 You should replace the overridden property types with String , or make them String? 您应该使用String替换覆盖的属性类型,还是将它们设置为String? in the interface. 在界面中。

The main problem is the type T? 主要问题是类型T? includes T and null . 包括Tnull in turn, T is a subset of T? 反过来, TT的子集T? . so you can't override the T property with its superset type, for example: 因此您不能用其超集类型覆盖T属性,例如:

interface Source { val content: Any }

//                               v--- ERROR: `Any?` is not a subtype of `Any`
class Image(override val content:Any?) : Source

However, you can override the T? 但是,您可以覆盖T? property with its subset type or subtype , for example: 属性及其子集类型子类型 ,例如:

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

Then your code should be as below. 然后您的代码应如下所示。 However, Kotlin is a null-safety system, you can't define a property without initializing it, even if the property is a nullable property: 但是,Kotlin是一个空值安全的系统,即使该属性是可空值的属性,也无法在不对其进行初始化的情况下对其进行定义:

class Airing : Media {
   //           v--- ERROR: the property isn't initialized      
   override val contentId: String
   ...
}

You should introduce properties in primary constructor to let the client code to initializing them in future, for example: 您应该在主构造函数中引入属性,以使客户端代码将来可以初始化它们,例如:

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 

You also can provide some default value for the properties, for example: 您还可以为属性提供一些默认值,例如:

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 function will conflict with getter , so you should remove it. AND getContentId函数将与getter冲突,因此应将其删除。

Variables declared as val are like Java final variables, are inmutable so you cannot set as Optional ? 声明为val的变量就像Java final变量一样,是不可变的,因此您不能将其设置为Optional ?

Your variable declaration should be like follows: 您的变量声明应如下所示:

interface Media {
    var contentId: String?
    //...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM