sul*_*man 1 inheritance scala typeclass case-class shapeless
假设我有一个case类定义如下:
case class User(name: String, age: Int)
Run Code Online (Sandbox Code Playgroud)
我想像这样重写它的toString
方法:
case class User(name: String, age: Int) {
override def toString: String =
s"name = $name
age = $age"
Run Code Online (Sandbox Code Playgroud)
这样,如果我跑步print(user.toString)
,我会得到:
name = nameOfUser
age = ageOfUser
Run Code Online (Sandbox Code Playgroud)
现在我有另一个类Computer
,它被定义为
case class Computer(make: String, RAM: int, clockSpeed: Double)
Run Code Online (Sandbox Code Playgroud)
我想为所有值打印相同的内容。我想要类似的东西:
make = makeOfComputer
RAM = RAMOfComputer
clockSpeed = speedOfComputer
Run Code Online (Sandbox Code Playgroud)
与其将上面的toString
函数复制,粘贴和调整到Computer
该类中,不如将其抽象化,以便任何case类都可以使用它。
我有一些想法可以使用
CaseClassType.unapply(caseClassInstance).get.productIterator.toList
Run Code Online (Sandbox Code Playgroud)
获取案例类的值,并
classOf[CaseClass].getDeclaredFields.map(_.getName)
Run Code Online (Sandbox Code Playgroud)
获取字段名称。这意味着我可以在不知道案例类的实际结构的情况下,找到案例类中所有值的列表以及所有字段名称的列表。
一旦有了这两个集合,就可以递归地遍历它们来创建字符串。我在想像下面这样的东西可以工作,但是不幸的是,scala不允许案例类继承自其他案例类。
case class StringifiableCaseClass(){
override def toString: String =
//get the values and the fieldnames and create a string
Run Code Online (Sandbox Code Playgroud)
我要做的就是扩展case类StringifiableCaseClass
,它们将能够创建正确的字符串。
我想使用案例类作为基本类型的原因是我可以使用
classOf[this.type]...etc
Run Code Online (Sandbox Code Playgroud)
和
this.type.unapply(this)...etc
Run Code Online (Sandbox Code Playgroud)
在中StringifiableCaseClass
。
关于如何实现给定的目标,我有什么想法无法将案例类扩展到其他案例类?
The base implementation does not have to be a case class. Just make it a trait, and then your case classes can all extend it.
trait Stringification { self: Product =>
override def toString() =
getClass.getDeclaredFields
.zip(productIterator.toSeq)
.map { case (a, b) => s"${a.getName}=$b" }
.mkString("\n")
}
Run Code Online (Sandbox Code Playgroud)
and then
case class Foo(foo: String, bar: Int) extends Stringification
case class Bar(foo: Foo, bar: String) extends Stringification
Run Code Online (Sandbox Code Playgroud)
... etc.