How to create immutable objects in Kotlin?
Asked Answered
S

2

8

Kotlin has a const-keyword. But I don't think constants in kotlin are what I think they are. It seems to very different to const in C++. It seems to me that its is only available for static members and to what are primitives in Java and do not compile for class-variables:

data class User(val name: String, val id: Int)

fun getUser(): User { return User("Alex", 1) }

fun main(args: Array<String>) {
    const val user = getUser()  // does not compile
    println("name = ${user.name}, id = ${user.id}")
    // or
    const val (name, id) = getUser()   // does not compile either
    println("name = $name, id = $id")
}

As this seems not to work, I think what i really want is a second class, that deletes the operations i don't want to support:

class ConstUser : User
{
    ConstUser(var name: String, val id: int) : base(name, id)
    { }
    /// Somehow delte the setters here?
}

The obvious downside to such a apprach is that I must not forget to change this class, in case i change User, something that looks very dangerous to me.

But I'm not sure how to do this. So the question is: How does one make immutable objects in ideomatic Kotlin?

Schoolgirl answered 24/8, 2019 at 7:45 Comment(1)
const is not about immutability. It's a signal for compiler to replace usages of such property with raw value during compile time. Immutability is achieved by not exposing mutating accessors. Compare Collection and MutableCollection interfaces in Kotlin stdlibCasabonne
D
11

The const modifier in Kotlin is used for compile-time constants. Immutability is done with a val keyword.

Kotlin has two types of properties: read-only val and mutable var. vals are equivalent to Java's finals (I don't know how this relates to const in C++, though) and properties or variables declared as such can't change their values once set:

data class User(val name: String, val id: Int)

val user = User("Alex", 1)

user.name = "John" // won't compile, `val` cannot be reassigned
user = User("John", 2) // won't compile, `val` cannot be reassigned

You don't have to hide or delete somehow any setters of val properties as such properties don't have setters.

Draggle answered 24/8, 2019 at 11:24 Comment(1)
Read-only properties are not necessarily immutable nor final. A read-only property can hold a mutable object: val list=mutableListOf(1,2,3) list.add(4) print(list)//[1,2,3,4]Busterbustle
L
1

To add to jsamol's answer:

  • For updating immutable objects, you can use copy() method.
    -- But beaware: It is just a shalow copy, semantically like the commented lines below.
data class Car(
    val make: String,
    val manufactured: ZonedDateTime,
    val color: String
) {
    fun repaint(newColor: String): Car 
         = copy(color = newColor)

    //fun repaint(newColor: String): Car 
    //   = Car(make = this.make, manufactured = this.manufactured, color = newColor)
}
Laliberte answered 27/2 at 13:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.