2
votes

Why it error when i make userName is public:

Error:(2, 5) Kotlin: Platform declaration clash: The following declarations have the same JVM signature (getUserName()Ljava/lang/String;): fun (): String defined in User fun getUserName(): String defined in User

Error:(4, 5) Kotlin: Platform declaration clash: The following declarations have the same JVM signature (getUserName()Ljava/lang/String;): fun (): String defined in User fun getUserName(): String defined in User

But i make userName is private is working fine

 class User{
            /*private*/ var userName: String = "Emily"

            fun getUserName(): String{
                return userName
            }
        }

        fun main(args: Array<String>){
            val User = User()
            print(User.getUserName())
        }
4

4 Answers

1
votes

When you define var userName you are really defining a property, not just a field. Along with the property comes an implicit getUserName() and setUserName() method. By adding your own getUserName(), you are shadowing the one Kotlin is creating for you automatically.

You can safely drop your getUserName() and the make your field non-private and it should work fine. The idiomatic way to write your code would be something like this:

class User {
    var userName: String = "Emily"
}

fun main(args: Array<String>){
    val user = User()    // Note changed val from User to user.
    print(user.userName) // Note, this really calls the getter
}
4
votes

By making your userName property public, Kotlin will create corresponding getUserName() and setUserName() functions for you. When it does this, writing your own getUserName() is redundant - the same function with the same signature is effectively present twice - and the compiler won't allow it.

If you want the userName field to be a public property (with a generated getter and setter), then you can't also write the getter yourself. This would be adequate:

var userName: String = "Emily"

If you wanted userName to have a public getter and a private setter (which seems like what you intended), this is the Kotlin way to do that:

var userName: String = "Emily"
    private set

And finally, you could still create custom accessors on a property (e.g., if you wanted extra logic, such as to return it lowercased). The Kotlin way to do that looks like this:

private var _userName: String = "Emily"
var userName: String
    get() = _userName.toLowerCase()
    set(value) { _userName = value }

Also, note that the way you access the property is different depending on whether you're accessing it from Kotlin or Java. From Kotlin, you just write user.userName, but in Java, you'd write user.getUserName().

1
votes

In Kotlin, a setter and getter is being created for every property (unless visibility prohibits it), e.g. for your userName which happens to be named exactly like the one you provided in addition: getUserName(). The result is a name clash. Note that for var, also setters are generated. Use val for read-only properties.

Actually, you don't need explicit getters like this. Simply do:

class User{
    /*private*/ var userName: String = "Emily"
}

//use property syntax
val user = User()
print(user.userName)
1
votes

I just want to add more about private field. When you declare a field with private modifier, Kotlin won't generate getter/setter

class User {

    private var userName = "Na"

    fun getUserName(): String {
        return userName;
    }

    fun setUserName(v: String) {
        userName = v
    }

}

And when you declare above methods (getter and setter) then these are treated as User Defined methods.