9

I'm converting some classes in Java to kotlin and I'm running into compile errors when trying to inherit from an interface:

Platform declaration clash: The following declarations have the same JVM signature (getContentID()Ljava/lang/String;):

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

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.

Kristy Welsh
  • 7,828
  • 12
  • 64
  • 106
  • Have you defined variables or functions in your interface Media? Looks like they are variables (properties in Kotlin). I think you want to define a list of functions (methods in Java) and implement them in `Airling` class. Is it ok? – lalosoft Aug 04 '17 at 15:20

3 Answers3

6

You don't need to declare override fun getContentId(): String?, because the val contentId: String from the Media interface is already overridden by 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).

In Kotlin, you should work with the property contentId directly, whereas in Java you can use the generated accessors getContentId() and setContentId(...).

Also, Kotlin does not allow you to override a not-null String property with a nullable String? one, because the users of the base interface will expect a not-null value from the property. You should replace the overridden property types with String, or make them String? in the interface.

hotkey
  • 140,743
  • 39
  • 371
  • 326
2

The main problem is the type T? includes T and null. in turn, T is a subset of T?. so you can't override the T property with its superset type, for example:

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? 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:

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.

holi-java
  • 29,655
  • 7
  • 72
  • 83
  • *Note*: this rule apply immutable `val` property, because override method can provide its return type with subtype in Java. in other words, you can't apply the rule in mutable `var` property. – holi-java Aug 04 '17 at 16:15
0

Variables declared as val are like Java final variables, are inmutable so you cannot set as Optional ?

Your variable declaration should be like follows:

interface Media {
    var contentId: String?
    //...
}
AlexTa
  • 5,133
  • 3
  • 29
  • 46