Property vs Field

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"
}

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.

1 Like

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?

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.

1 Like

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.

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).

1 Like

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.

1 Like

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.

2 Likes

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
}
2 Likes

@dalewking @fatjoe79 The whole confusion about property vs field is caused by the language reference article https://kotlinlang.org/docs/reference/properties.html that in 2020, 2 years after this discussion, has the same confusing reference to a “field” without telling if and what it really means in Kotlin language (comparing e.g. to a “field” in Java language).
And this is why I read this thread and don’t have any “authoritative” answer…

Maybe “field” is just a convenience reference similar to “it” ?!

But maybe this is still unclear for Kotlin language authors also?

1 Like

Field means backing memory. Properties can be either synthetic or memory backed. The memory backing the property is called the field and can be accessed through the field symbol in the getter/setter.

Conceptually properties always have getters (and setters for mutable properties). By default those are trivially implemented to give direct access to the backing field/memory.

In practice the compiler (and jit in case of JVM) applies optimizations, for example eliding default getters/setters for private properties (they can be trivially inlined and can not be used outside the class). They could be used as method references though, in which case they have to be generated.

If you want to understand a language you normally want to stay away from compiler optimizations though as the details of that will add to confusion not resolve it. (Having said that some language make promises about optimizations that can be critical to efficiency, but normally even those don’t change the semantics of the code).

2 Likes

If the confusion comes from that reference page, then it seems that page should be slightly edited to explain it better. IMO this discussion is on the definition of properties vs fields and doesn’t need Kotlin reference to explain it much more then it already does.

Properties are pretty common in modern languages these days. Even if a beginner doesn’t understand the difference it’s unlikely to cause an issue.
IMO this topic has gone as follows:

OP: Properties vs Fields? Aren’t they defined by what is generated in bytecode?

Replies: No. The concept of a property is what defines it, not the generated bytecode.

Thank you, I suspected that the word “field” here means “memory backed instance of a property value…”, but it was strange for me that the new (in the language) term is used (even in the Language reference section title!) without any explanation, as if its meaning is obvious :slight_smile:

I agree with @arocnies that the reference page needs some edition.
I would suggest not to use the term (backing) “field” at all in a pure Kotlin context explaining the “field identifier”, as it is not clear if Kotlin really needs this new term. Replacing confusing “Backing fields” with “Memory-backed values/instances…”

And use “field” term where specs describe e.g. mapping to Java / JVM etc., for which the “field” term has specified meaning (“variables of a class type” in Java spec…)

Are you aware that Kotlin language has a “field” keyword/identifier which can be used in custom getter/setter. This part of the documentation might be referring to that identifier.

1 Like

Am I understanding correctly that you see the confusion coming from the use of the word “field” or “backing field” compared to properties?

Personally, I do not think we should change the wording. I like how the reference lays it out. The section on backing fields is immediately followed by a section on backing properties. The doc also uses phrasing like “implicit field”.

The phrase “backing field” is used in other places used for describing properties in C# and Groovy. In Swift I’ve seen “backing” used. Other languages like Dart “backing field” is unofficially used. The phrase is also used talking about things other than properties (like mapping a value to a backing field in another data structure).

I think the word choice fits well. In addition to the existing usage already common in Kotlin docs and C#, there’s quite a lot of documentation and tutorials for Kotlin that use this phrasing.

It still might be worth editing the docs if they’re a source of confusion but I can’t think of a better phrasing to use.

I’m curious how often this comes up–we only got one more post expressing pain for this topic in the last 2 years. Either people aren’t posting about it, the issue has mostly been resolved, or more developers are familiar with the phrasing these days.

No. This is not about word choice.
Confusion comes from a reader’s feeling that in Kotlin, in addition to a “property”, we have some separate “field” thing that is “backing” the property… Whereas in fact there is no such thing, and the spec actually talks about “memory backed instance of a property value…”

There is no problem in “field identifier” used by the Kotlin language (like “this” or “it”).

I think not many people read or try to understand specs as deep as we do in this thread. :slight_smile:
Personally I’m not surprised at all that some thing in the spec, that seemed OK for years, actually needs correction.
Moreover, I can think that in the early Kotlin days no one was surprised with “Java things” appearing in the Kotlin spec, so readers understood references to some “backing field” as references to “Java specified field thing” (or as references to a “field” thing in another familiar language).

1 Like

I don’t understand how you conclude that there is no such thing. There is a field in the byte code as well as in the Kotlin language itself. And in both those levels it is conceptually not the same thing as the property.

Furthermore in Kotlin there are 2 kinds of properties, those that are backed by a field, and those that are computed on demand. Understanding the difference is very important, and the first step in understanding them is understanding the backing field.

Would it be better to call the backing field something different? Maybe. Then again, you say that the wording is not the issue.

2 Likes

Please re-read at least yesterday’s posts, and the spec’s page that we are referring to here.
And we are NOT talking about byte code.

My opinion is that we better think about “field identifier” as a part of the property, related to its “memory backing” / state (“memory backed instance of a property value…”). And not as another thing, separate from a property. Because this is simpler, and because this doesn’t require to invent and to write into the spec anything about that “backing field”.

Ah, I think I’m better understanding what you’re saying :slight_smile:
I imagine a change that aligns with that would be to change some of the focus under backing fields from the technical implementation of fields to a focus on fields as an aspect of properties.

I can pick out specific sentences in the reference that put fields in light of their implementation instead of the conceptual part. I’d say we still need those details but maybe someone has a better idea of introducing fields in a more conceptual way.
Maybe the first line (the one that prompted this topic):

Fields cannot be declared directly in Kotlin classes.

Could be reworded to something like:

In Kotlin, fields are only used when needed as part of a property

Haha yes! Topics in language design seem to become more esoteric and interesting with time :stuck_out_tongue_winking_eye:

1 Like

Maybe even change it to

In Kotlin, fields are only used when needed as part of a property and can not be declared directly.

Also it might be worth changing the title of the page from “Properties and Fields” to just “Properties”. After all fields are always a part of a property and can’t exist independently (at least on a language level. In the bytecode private properties/const properties are often represented by just the field but that’s not important here).

Yes, but this is not a “spec” in the technical term. This is part of the documentation I and others point to when newcomers to kotlin ask questions so it should be understandable for everyone.