Scala: переопределить toString, чтобы кавычки печатались вокруг строк
Я хотел бы написать функцию "toSource", которая будет генерировать исходный код для базовых классов. Например, я хотел бы:
case class Person(name: String, age: Int)
val bob = Person("Bob", 20)
println(toSource(bob)) // Should print """Person("Bob", 20)"""
Функция "toString" почти дает мне то, что я хочу, но она сбрасывает кавычки вокруг строк:
println(bob.toString) // Prints """Person(Bob, 20)"""
Есть идеи, как это сделать?
2 ответа
Решение
Вы можете использовать тот факт, что тематические классы смешиваются в чертах Product
:
def toSource(p: Product): String =
p.productIterator.map {
case s: String => "\"" + s + "\""
case other => other.toString
} mkString (p.productPrefix + "(", ", ", ")")
toSource(Person("Bob", 20)) // yields """Person("Bob", 20)"""
Опираясь на решение, предоставленное0__
, я написал этот подход, который работает с классами, которые используют только несколько примитивных типов:
object Main {
def toSourcePrimitive(l: Long): String =
l.toString + "L"
def toSourcePrimitive(i: Int): String =
i.toString
def toSourcePrimitive(s: String): String =
"\"" + s.replace("\"", "\\\"") + "\""
def toSourcePrimitive[T](li: List[T]): String =
"List(" + li.map(toSource).mkString(", ") + ")"
def toSourcePrimitive[T](op: Option[T]): String =
if (op.isEmpty) "None" else "Some(" + toSource(op.get) + ")"
def toSourcePrimitive(p: Product): String = {
p.productIterator.map(toSource).mkString(p.productPrefix + "(", ", ", ")")
}
def toSource(a: Any): String = a match {
case in: Int => toSourcePrimitive(in)
case ln: Long => toSourcePrimitive(ln)
case s: String => toSourcePrimitive(s)
case li: List[_] => toSourcePrimitive(li)
case op: Option[_] => toSourcePrimitive(op)
case p: Product => toSourcePrimitive(p)
case _ => "ERROR"
}
case class Example1(date: Int, numLong: Long, numInt: Int)
case class Example2(v1: String, v2: List[String], v3: List[Example1], v4: Option[String])
def main(args: Array[String]): Unit = {
println("\nExample 1:")
println(toSource(Example1(20220105, 6L, 10)))
println("\nExample 2:")
val elems = List(
Example2("blah", List("one", "two"), List(Example1(20220105, 6L, 10)), Some("three")),
Example2("blah", Nil, List(Example1(20220105, 6L, 10)), None)
)
println(toSource(elems))
}
}
Результат показан ниже:
Example 1:
Example1(20220105, 6L, 10)
Example 2:
List(Example2("blah", List("one", "two"), List(Example1(20220105, 6L, 10)), Some("three")), Example2("blah", List(), List(Example1(20220105, 6L, 10)), None))