78

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?

iknow
  • 8,358
  • 12
  • 41
  • 68
  • 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. – Sonique Jun 20 '17 at 09:15

2 Answers2

143

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
}
hotkey
  • 140,743
  • 39
  • 371
  • 326
  • One can use `this` as representing the current class instance inside `toString` body – Paulo Buchsbaum Oct 02 '19 at 14:12
  • 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. – GMX Jan 09 '20 at 11:15
  • 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. – vonWippersnap Mar 17 '21 at 05:03
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

wf9a5m75
  • 6,100
  • 3
  • 25
  • 59