在下面的示例中,我试图声明一个类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的形式携带格式信息。
答案 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
已经具有有效的+
函数,编译器将如何知道您的意图,并且探索所有可能的转换并不是很有效。