How to extend a data class with toString
Asked Answered
S

2

80

I have created a data class

data class Something (
    val a : String,
    val b : Object,
    val c : String
)

as later in my program, I need the string representation of this data class I tried to extend the toString method.

override fun Something.toString() : String = a + b.result() + c

The problem here is, it does not allow extending (overriding) the toString function, as it is not applicable to top-level functions.

How to properly override/extend the toString method of a custom dataclass?

Shimberg answered 13/3, 2016 at 13:41 Comment(1)
Kotlin also have pretty nice toString() implementation by default, that print all members of data class. So in most cases it's enought for debugging etc.Harpp
H
148

Adding a .toString() extension function would not work because:

  • Extension functions can't take part in virtual calls (they are resolved statically). In other words, extensions cannot override member functions.
  • If there is a matching member function, it is preferred to the extension. If you add an extension function fun Something.toString() = ..., then s.toString() won't be resolved to it, because the corresponding member inherited from Any wins.

But in your case, nothing stops you from overriding toString inside Something class body, because data classes can have bodies just like regular classes:

data class Something(
    val a: String,
    val b: Any,
    val c: String
) {
    override fun toString(): String = a + b + c
}
Hermaphrodite answered 13/3, 2016 at 13:47 Comment(3)
One can use this as representing the current class instance inside toString bodyRoderick
is there a possibility to autogenerate the String? This solution work but is really long to write if you have a lot of proprieties in your class.Kore
If you want a string with all the properties (e.g. for debugging) that is what data classes automatically generate by default. You only need to manually write this function if you don't like the default output format.Andalusite
U
0

data class UsDoller (
    val amount: Int,
) {
    init {
        if (this.amount < 0) {
            throw Exception("The amount be greater or equal than 0")
        }
    }
    
    fun add(other: UsDoller): UsDoller {
        return this.copy(
            amount = this.amount + other.amount,
        )
    }
    
    override fun toString(): String {
        return "${this.amount} USD"
    }
}
data class User constructor(
    val name: String,
    val money: UsDoller,
) {
    
    override fun toString(): String {
        return "${this.name} (${this.money})"
    }
}
fun main() {
    var user = User(
        name = "Someone Unknown",
        money = UsDoller(23),
    )
    user.money.add(UsDoller(100))
    println(user.toString())
}

https://pl.kotl.in/ZNz_vgbmV

Upshot answered 30/7, 2023 at 0:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.