Scala - 绕过重写的 toString 方法

标签 scala overriding tostring pretty-print

不幸的是,给定一个案例类覆盖了 toString 方法,有什么方法可以绕过该方法吗?

即:

case class Foo(s:String){
    override def toString = s
}

然后

val foo = Foo("Hello World")
println(foo)

将会产生

Hello World

如果我只给出了 foo (但不是 Foo),我可以对 foo 执行任何操作以便打印

Foo(Hello World)

而不仅仅是字符串?

最佳答案

使用 Show 类型类(如 0__ 所示)是一个不错的选择。不幸的是 toString 如此普遍(很多代码依赖它来格式化给定对象的字符串),以至于在很多情况下类型类不会有任何好处。例如,如果您有一个 List[Foo],则对其调用 toString 将调用 Foo.toString。使用类型类的正确解决方案是为列表定义一个实例,该实例本身将调用 Foo 实例上的 show 。但这只会把问题推得更远,因为很可能会发生这样的情况:您将此列表传递给您无法控制的某些第三方代码,并且该代码将调用 List.toString (而不是Show.show)。在这种特定情况下,唯一可行的解​​决方案是将 Foo 类包装在您自己的类中(例如 MyFoo)并在那里重写 toString 。显然,只有当您可以将 List|[Foo] 更改为 List[MyFoo]

时,这才有用
implicit class MyFoo(val foo: Foo) extends AnyVal {
    override def toString = s"Foo(${foo.s})"
}
object MyFoo {
 implicit def unwrap(myFoo: MyFoo): Foo = myFoo.foo
}

重复测试:

scala> val list1: List[Foo] = List(Foo("foo"), Foo("bar"))
list1: List[Foo] = List(foo, bar)

scala> val list2: List[MyFoo] = List(Foo("foo"), Foo("bar"))
list2: List[MyFoo] = List(Foo(foo), Foo(bar))

如您所见,list2 的字符串表示形式使用您自己的toString 实现。 显然,这个解决方案并不理想。在许多情况下,它甚至可能完全不切实际(例如,您无法将 MyFoo 传递给需要 Foo 的方法)。如果有的话,它表明依赖于 Any 中的 toString 方法并不是最好的设计,但遗憾的是,我们必须使用大量代码(包括整个 java 生态系统)就是这样做的。

因此,如果您无法控制谁将调用 Foo.toString (这意味着您无法将该调用更改为其他任何内容,例如 Show.show)你可能无法做得更好。

关于Scala - 绕过重写的 toString 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31537711/

相关文章:

scala - Spark scala mocking spark.implicits 用于单元测试

Scala 隐式和覆盖问题

java - 这是方法隐藏的情况吗?

java - 在子类中覆盖 equals() 和 hashCode() ...考虑 super 字段

c# - 从转换为字符串的路径中删除\"

scala - Spark SQL datediff 以秒为单位

Java - 隐藏重写和修饰符 final

Java奇怪的Integer.parseInt问题(java新手)

c# - 如何在字符串中自动显示类的所有属性及其值?

java - 如何知道一个 Actor 是否存在于 Actor 系统中