I thought that Kotlin had properties instead of in...
# getting-started
e
I thought that Kotlin had properties instead of instance variables, but ChatGPT is telling me otherwise:
In Kotlin, a property is a field that has additional logic associated with it, such as a getter and a setter. A property can be either a
val
(read-only) or a
var
(read-write).
An instance variable, on the other hand, is a field that is declared directly within a class. It does not have any additional logic associated with it and can be accessed directly from instances of the class.
Does Kotlin have instance variables (distinct from properties)?
c
Properties and backing fields per the docs.
g
(I don't know about JS and Native platform, so I am talking about JVM.) Any declared variable is property variable (with or without backing field) if and only if it is property of some entity (class, interface, or object) and/or it is delegated. So variable is an "instance variable" if it is declared locally. The only exception of the rule is property variables with backing field annotated with
@JvmField
. It will be translated to good old field. For example,
Copy code
abstract class A {
    val var1 = 5 // this is a property variable with a backing field

    abstract val var2: Int // this is a property variable without a backing field

    lateinit var var3: String // this is a property variable with a backing field as well

    fun action() {
        val var3 = var1 * (var1 + 1) // this is an instance variable

        val var4: Int // this is an instance variable as well

        val var5 by lazy { 15 } // this is a property variable
    }
}

val A.var6 get() = "Hello, var5" // this is a property variable too
c
Variables are different than properties. Kotlin properties are what you use/declare in a class, and have several possible implementations - implicit backing fields, backing properties (custom getter).
e
Thanks, everyone. It sounds like it was wrong to distinguish between properties and instance variables, especially with the definition it gave. kotlinlang gives this example of properties (with no additional logic):
Copy code
class Address {
    var name: String = "Holmes, Sherlock"
    var street: String = "Baker"
    var city: String = "London"
    var state: String? = null
    var zip: String = "123456"
}
https://kotlinlang.org/docs/properties.html
ChatGPT may have gotten its wrong idea from features such as backing fields and custom getters.
c
ChatGPT is just a text aggregator for the entire internet. It's not going to be able to answer technical questions correctly. Trust the documentation.
5
e
It generated and defended this code, which does not compile:
Copy code
class ArrayList<T> : List<T> {
    private var array: Array<Any?> = arrayOfNulls(10)
    private var size = 0

    override val size: Int
        get() = size
it defended its reuse of the name
size
but the compiler said otherwise.
😆 1
c
Looks like ChatGPT made a bad assumption that class properties are simply variables that are scoped to the class (they aren’t), though they are in other languages (e.g. Java).
j
We can use properties outside of classes at the top level as well. I'd also consider a property inside a class a "instance property". I think we have two different semantics we are mixing together as there is a difference between a property and variable. But there is also a difference when we introduce the word "instance".
c
No. Terminology matters. Those aren’t properties, they are variables. The docs define a shared vocabulary for all this.
e
@CLOVIS I totally agree. I'm a professor preparing to tell my students the risks of using ChatGPT. I just want to make sure that it was actually mistaken and that I hadn't taught my students the wrong thing last semester. 😄
Thanks for ungaslighting me: 💡
It sounded so confident. 😃
j
@Chris Lee do top level variables have a backing field? If not then yeah you're right, I appreciate the correction!
c
top level variables are simply variables. Backing fields only come into play with properties (which may or may not have a backing field).
well, they could be constants too at the top level.
c
Who could have expected that using the entire internet to teach an AI would result in an expert gaslighting machine? 😅 If you want to confuse yourself even more: (local) variables can be delegated (e.g. to
lazy
) but can't have custom getters or setters
e
I don't like to use gendered insults, but I was amused when someone described it as "mansplaining as a service".
j
"Kotlin has had top-level functions and properties from day one. They are very convenient in many cases: from basic utilities to extensions for standard APIs." Found this in a Kotlin blog, to be honest I get kind of confused as I also looked over the property documentation but the only top level it mentions are constants
c
yea, the wonders of Internet references 🤦 . The official docs are what we should be going by; from that (and experience) there are no top-level properties, only variables and functions.
c
@Chris Lee what's your definition of property? I've always seen it defined as "something that looks like a variable, but can have a custom getter/setter". With that definition, all top-level "variables" are properties except when marked with
const
.
c
For Kotlin I’m using the documented definition, which specifically defines them (i.e. not in terms of something else). Agreed, though, there are similarities.
all top-level “variables” are properties except when marked with
const
Well, almost - you can’t have custom getter/setter on variables. You can do delegation and control mutability.
j
So according to the official docs here under properties it also says that they are considered properties at top level: https://kotlinlang.org/docs/coding-conventions.html#property-names
c
yea. inconsistencies in docs. that’s the only place I’ve seen variables called properties. btw, you can have const properties in companion objects.
j
Well the docs you reference are specifically only talking about properties in classes. I don't think it's an inconsistency. I haven't found any documentation that says they are called variables when they have the global top level scope. They can still have backing fields when at top level, they just aren't tied to an instance right?
Well to be "technically correct". It does refer to them as variables, but they are specifically property variables
c
The docs don’t define variables in terms of properties, or properties in terms of variables - they’re treated as separate constructs, which have some similarities (that we observe, not that the docs point out). Variables are defined here. Yes, variables (unless delegated, or const) represent storage of a value (not using “field” or “instance” or avoid confusion).
So looking for something less subjective than interpreting the docs - the Kotlin grammar is available. It offers more precision than the docs. -
propertyDelcaration
is both top-level and class-level, from a grammar perspective, though from a semantics perspective there are differences.
j
though from a semantics perspective there are differences.
Are those the differences that was discussed above about
const
and things like delegation?
c
exactly those, yes, though looking at the grammar I’m wondering about a few things, one sec…
j
I love that you found the kotlin grammar site, good to know it exists 👍
c
yea, hadn’t seen it before, helps clarify things!
j
That's one thing I wish they elaborated on a bit more in the Properties page we reference, they don't actually start it off by saying what a property is in Kotlin, they just start it off by saying how to define one. Then everyone has to get on the same page as to what specific terminology means
c
yea, exactly. So, it looks like top-level variables and properties are largely symmetrical
Copy code
public class Foo {
    public val bar : String
        get() = "whatever"

    public val xyz: String = "abc"

    public var zzz : String = "Abc"

    public val lazyThing : Lazy<String> = lazy { "abc" }

    public companion object {
        public const val something: String = "someconst"
    }
}
public val bar : String
    get() = "abc"

public val xyz: String = "abc"

public var zzz : String = "Abc"

public const val something : String = "whatever"

public val lazyThing : Lazy<String> = lazy { "abc" }

// can't do this directly in a class, only in a companion object
public const val sss: String = "abc"
custom getters, setters; delegation are there for each. slight differences with const (needs to be in a companion object for classes).
Differences for local variables:
Copy code
public fun something() {
    // no-go - doesn't compile
//    val bar : String
//        get() = "abc"

    val xyz: String = "abc"

    var zzz : String = "Abc"

    // no-go - doesn't compile
    //const val something : String = "whatever"

    val lazyThing : Lazy<String> = lazy { "abc" }
}
local variables are also a
propertyDeclaration
according to the grammar but are scoped down in their capabilities.
j
That follows my current understanding of kotlin, thanks for looking into that!
k
Are we going to argue with bots now? 👀
e
And so it begins…