Property vs Field


#1

Hi, everyone!

While reading documentation about Properties and Fields I found some information that I don’t understand:

Fields cannot be declared directly in Kotlin classes.

But why? As I understand the difference between property and field is that first have accessors and the second doesn’t.

If I declare private field in class, kotlin doesn’t generate default accessors. And I have a field, isn’t it?

class Foo {
    private var someField: String = "This is a field, not a property"
    var someProperty: String = "This is a property, not a field"
}

#2

Not quite. Even a private var is still a property with a getter and setter, and you can still provide custom accessors if you want. The only way you can have a field, is if your property has a backing field. A backing field cannot be declared directly, and can only be accessed within a custom accessor through the someProperty.field syntax.


#3

If I decompile this kotlin code:

class Foo {
    private var someField: String = "This is a field, not a property"
}

It’ll be this java code:

public final class Foo {
   private String someField = "This is field, not property";
}

There is no getter and setter on a private var. But I can still provide them, and when I provide them this field will became a property. Or no? And why?


#4

When accessing private properties, the compiler will optimize calls to the default accessors away. So for all purposes, a private property without custom accessors is equivalent to a field in Java. In Kotlin terms, however, it is still considered a property. Admittedly, at this point it is mostly a matter of terminology.


#5

What are the default accessors of a private field which compiller will optimize calls? If field is private kotlin does’t generate any accessors and we cannot access them out of class.


#6

The accessors do not exist in the byteode as the compiler has optimized away completely. At this point, the difference between property and field is simply a matter of terminology: Java has fields, Kotlin has properties (which may have backing fields).


#7

We must distinguish between what a property is conceptually. And how they are implemented internally on the jvm. Conceptually Kotlin knows only properties. You cannot manually declares fields in Kotlin. However this does not mean that the bytecode needs to follow this.


#8

You can for specific platforms using platform specific annotations, i.e. @JvmField. Not sure off the top of my head if there are equivalents for Kotlin-JS and Kotlin-native.

That does not contradict your statement as that is not part of Kotlin as a language, but no one had mentioned @JvmField in the thread.


#9

Actually they may or not be. Consider this code which does generate getI and setI methods:

class Foo{
    private var i = 5
    
    fun bar() = this::i.getter
}