如何重载 Kotlin 的字符串模板运算符(美元符号)?

How do I overload Kotlin's string template operator (the dollar symbol)?

我确定我已经读过 Kotlin 的字符串模板的“美元运算符”可以重新定义,但是他们的documentation on operator overloading does not indicate how to overload it, and their documentation on string templates,就像大多数关于字符串模板的在线教程一样,只告诉你如何使用美元象征。在 Whosebug 上搜索同样没有发现解决此问题的明显问题。

有没有办法重载 Kotlin 字符串模板运算符,也就是美元符号?

举个例子:

data class Point(x: Int, y: Int)
data class Stick(val p: Point, val q: Point)
console.log('${ Stick( Point(2,1) , Point(1,7) ) }')

输出为

Stick(p=Point(x=2, y=1), q=Point(x=1, y=7))

但我不想这样。我要

[ ( 2 , 1 ) ; ( 1 , 7 ) ]

我该怎么做?

覆盖 Stick class 的 toString() 方法:

data class Stick(val p: Point, val q: Point) {
   override fun toString() = "[ ( ${p.x} , ${p.y} ) ; ( ${q.x} , ${q.y} ) ]"
}

我不知道它出现在文档中的什么位置,但我确定我已经看过它。

您不能在字符串模板中重载 $ 运算符。

但是,那只是获取对象或表达式的值;字符串模板通过调用其 toString() method.  Every object implements that method — it's defined in the Any type that every object inherits from.  (And there's also an extension method 将每个对象转换为字符串,因此它也适用于 null。)

所以你可以简单地重写toString();每当对象在字符串模板中使用时都会生效 - 并且在其他任何地方都会将其转换为字符串(例如,如果直接传递给 println() 或记录器)。

在这种情况下,我认为为 both 个对象提供自己的 toString() 实现会更灵活,例如:

data class Point(val x: Int, val y: Int) {
    override fun toString() = "( $x , $y )"
}

data class Stick(val p: Point, val q: Point) {
    override fun toString() = "[ $p ; $q ]"
}

提供您自己的 toString() 是使您的对象更普遍有用的一种方法。 data class 为您提供的标准实现清晰易读,但冗长冗长,因此提供您自己的实现是很常见的。 (对于 不是 data classes 的 类,从 Any 继承的实现非常神秘——例如 Stick@60652518——所以重写更重要!)

一般来说,toString()倾向于针对程序员(例如在日志中显示)。因此,如果这可能与您想要向用户显示的内容不同,那么您可能希望为后者添加一个单独的方法(特别是如果它只需要显示部分数据,或进行更多处理,例如将其转换为用户的语言)。