Ilham Bagus Bahrudin
Ilham Bagus Bahrudin

Reputation: 79

I have a question about generic in kotlin

I got an error. Like this :

Error 1 : Platform declaration clash: The following declarations have the same JVM signature (getData()Ljava/lang/Object;): fun (): I defined in typeErasure2 fun getData(): I defined in typeErasure2

Error 2 : Platform declaration clash: The following declarations have the same JVM signature (getData()Ljava/lang/Object;): fun (): I defined in typeErasure2 fun getData(): I defined in typeErasure2

fun main(args : Array<String>){
    var te = typeErasure("Jennie")
    println(te.getData())
    var te2 = typeErasure2("Sam")
    println(te2.getData())
}

class typeErasure<I>(name : I){
    private val data : I = name
    fun getData() : I = data
}

class typeErasure2<I>(name : I){
    val data : I = name          // error 1
    fun getData() : I = data     // error 2
}

when I use the private keyword the program can run, otherwise it will get an error. anyone can explain to me? :)

Upvotes: 0

Views: 124

Answers (2)

Animesh Sahu
Animesh Sahu

Reputation: 8096

Kotlin's logic of properties differ slightly from Java's fields.

Whenever you declare any variable in class, its getter and setters are automatically generated, and they can be customized with get() or set {} after it.

Declaring getVariable() manually will result in platform clash, as getter is already defined for the field in the variable declaration and you are creating function with the same name as well.

You can use @JvmField annotation to instruct the compiler to not generate any getter or setter for the field.

@JvmField
val data: I = name

fun getData(): I = data

Upvotes: 1

birgersp
birgersp

Reputation: 4916

This has nothing to do with generics. The problem with your code is that

public fun getData(): I

Is an accesor for "data". But when "data" is a public field, then the accesor is redundant. So when you do:

val someValue = myObject.data

Then the compiler cannot tell if it should use the accessor getData() or it should just point to the field directly.

When getData is private, then the compiler clearly knows that it can't use it so then it will point to the field directly.

class typeErasure2<I>(name : I){
    val data : I = name
    fun getData() : I = data
}

fun main() {
    val obj = typeErasure2<Int>(123)
    println(obj.data) // <--- Ask yourself, what does this line do exactly?
}
class typeErasure2<I>(name : I){
    val data : I = name
    private fun getData() : I = data
}

fun main() {
    val obj = typeErasure2<Int>(123)
    println(obj.data) // <--- Here it is clear
    // it is not the "getData" because that one is private,
    // so it must be the public field "data" you are pointing to
}

Upvotes: 2

Related Questions