首页 > 解决方案 > String 上的重载加 `+` 运算符

问题描述

在下面的示例中,我试图声明一个类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实例被转换为 a 。String"a"

如何更改WrappedString和/或隐含的声明,以便在第三个示例中,在应用运算符之前将其String转换为 a ?WrappedString+

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

标签: scalaoperator-overloading

解决方案


编译器永远不会选择隐式+方法而不是显式+方法,这是String类所拥有的,所以"a" + WrappedString("b")总是会变成"a".+(WrappedString("b").toString).

要强制转换,您可以选择一个不同的方法名称,一个String没有的方法名称,以及一个隐式类,这意味着它不能是一个case类。这样你就不需要implicitConversions导入,这是不鼓励的。

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

WrappedString("a") +# WrappedString("b") // [ab]
WrappedString("a") +# "b" // [ab]
"a" +# WrappedString("b") // [ab]
"a" +# "b" // also [ab]

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


推荐阅读