如何使用toString扩展数据类

78

我已创建了一个数据类

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

后面在我程序中稍后, 我需要这个数据类的字符表示,所以我尝试扩展toString方法。

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

问题在于,它不允许扩展(覆盖)toString函数,因为它不适用于顶级函数。

如何正确地覆盖/扩展自定义数据类的toString方法?


1
Kotlin默认也有非常好的toString()实现,可以打印数据类的所有成员。因此,在大多数情况下,它足以用于调试等。 - Sonique
2个回答

143

添加.toString()扩展函数不起作用,因为:

  • 扩展函数无法参与虚拟调用(它们在静态地被解析)。换句话说,扩展无法覆盖成员函数。
  • 如果存在匹配的成员函数,则优先使用成员函数。如果您添加一个扩展函数fun Something.toString() = ...,则s.toString()不会被解析为它,因为从Any继承的相应成员函数会胜出。

但在您的情况下,没有什么可以阻止您在Something类体内覆盖toString,因为data类可以像普通类一样有类体:

data class Something(
    val a: String,
    val b: Any,
    val c: String
) {
    override fun toString(): String = a + b + c
}

toString 方法体内,可以使用 this 表示当前类实例。 - Paulo Buchsbaum
有没有可能自动生成字符串?这个解决方案可行,但如果您的类中有很多属性,编写起来会非常冗长。 - GMX
如果您想要一个包含所有属性的字符串(例如用于调试),那么数据类默认会自动生成这个字符串。只有在您不喜欢默认输出格式时,才需要手动编写此函数。 - vonWippersnap

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接