在字符串上重载加`+`运算符

时间:2018-07-20 13:16:02

标签: scala operator-overloading

在下面的示例中,我试图声明一个类WrappedString,该类仅包装了String [1]。我希望能够将这些实例与+运算符连接起来,并在需要时将普通的String实例自动转换为WrappedString实例。

因此,+运算符存在三种可能的应用程序,它们应返回一个WrappedString实例,并在示例底部以对println()的调用进行说明。

import scala.language.implicitConversions

object test extends App {
  case class WrappedString(value: String) {
    override def toString = s"[$value]"
    def +(right: WrappedString) = WrappedString(value + right.value)
  }

  object WrappedString {
    implicit def fromString(value: String) = WrappedString(value)
  }

  implicit class StringExtensions(value: String) {
    // Isn't actually used in the code below.
    def +(right: WrappedString) = WrappedString(value) + right
  }

  println(WrappedString("a") + WrappedString("b")) // [ab]
  println(WrappedString("a") + "b") // [ab]

  // Would like this to print `[ab]`
  println("a" + WrappedString("b")) // a[b]
}

由于某些原因,第三个示例将打印a[b]。在将WrappedString实例转换为String之前,将其与字符串"a"串联以产生最终结果。

如何更改WrappedString和/或隐式的声明,以便在第三个示例中,将String转换为WrappedString之前的+被应用了吗?

[1]:在我正在处理的项目中,包装的字符串以ANSI SGR escape codes的形式携带格式信息。

2 个答案:

答案 0 :(得分:1)

编译器将永远不会选择隐式+方法而不是显式+方法,String类拥有这种方法,因此"a" + WrappedString("b")将始终成为{{1 }}。

要强制进行转换,您可以选择一个不同的方法名称,即"a".+(WrappedString("b").toString)没有的方法名称,以及隐式类,这意味着它不能是String类。这样一来,您就不需要进行case导入了。

implicitConversions

如果您不使用标准库中已经存在的类名,这可能也会有所帮助。

答案 1 :(得分:0)

我想知道当您手动将所有值自动包装在WrappedString中时,您实际上想要隐式转换的地方。似乎您需要类似右关联的运算符,Scala支持在函数名称末尾使用:

例如:

case class WrappedString(value: String) {
    override def toString = s"[$value]"
    def +(right: WrappedString) = WrappedString(value + right.value)
    def +:(right: WrappedString) = right + WrappedString(value)
}

println("a" +: WrappedString("b")) // [ab]

除此之外,您可以通过指定以下类型来强制转换:

println(("a": WrappedString) +: WrappedString("b")) // [ab]

或者可能只是将其移至单独的功能。很高兴得到纠正,但是由于String已经具有有效的+函数,编译器将如何知道您的意图,并且探索所有可能的转换并不是很有效。