Direct property accessor invocation

Suppose we have a property with default accessors

 class Person() {
 var name = "Bob"
}

Am I right I cannot call the default accessor directly?

I mean, instead of

 val person = Person()
 var personName = person.name

I cannot write

 val person = Person()
 var personName = person.getName()

But when I try to define fun getName(): String inside Person class I’m getting an error

Platform declaration clash: The following declarations have the same JVM signature

I could not find any explanation neither in documentation nor in the language specification. For me it looks inconsistent: I should either be able to call accessors directly or should not get such an error (which is not possible due to JVM limitations, I suppose).

It would be nice to have some mention of such behaviour in the Kotlin documentation, I guess.

When you write:

var personName = person.name

…then you are calling the default accessor! It looks like a direct field access, but it’s not (as you can verify if you try to access it from Java).

In Kotlin, a property consists of:

  • A getter method.
  • A setter method (if a var).
  • A private backing field (if needed).

The only necessary item there is the getter method; if you provide custom accessor(s) which don’t refer to the field, then there is no field.⠀(That’s how interfaces can have fields in Kotlin.)⠀But you can still access the property the same way, because you’re not accessing the field directly.

Unless you use an annotation to change its name, the getter is called getXxx() (or isXxx() if boolean) in the bytecode.⠀That’s why you get the error if you try to declare your own method with the same name.

And whenever you access a property, even though the syntax looks like a direct field access, it’s really calling the getter or setter.⠀Kotlin is taking the standard Java design pattern of private fields with accessors, and making it much simpler to use — but down at the bytecode level, it’s implemented the same way, for the sake of interoperability.

In fact, this is explicit in the language specification, at the bottom of the section you linked to:

Read/write access to the property is replaced with getter/setter invocation respectively.

2 Likes