让我们说我有这门课
case class Test (id: Long, name: String)
Run Code Online (Sandbox Code Playgroud)
和这个类的一个实例:
Test :
id -> 1
name -> toto
Run Code Online (Sandbox Code Playgroud)
我想创建一个Map [String,String]如下:
Map( "id" -> "1", "name" -> "toto")
Run Code Online (Sandbox Code Playgroud)
我的问题是:有没有办法将这个Test实例转换为Map [String,String]?我想避免使用这样的方法:
def createMap(instance: Test): Map[String, String] = {
val map = new Map[String, String]
map.put("id", instance.id.toString)
map.put("name", instance.name)
map
}
Run Code Online (Sandbox Code Playgroud)
如果在Scala中没有方法可以这样做,有没有办法迭代类属性?也许我可以创建一个通用函数来执行此操作:
def createMap(instance: T): Map[String, String] = {
val map = new Map[String, String]
//pseudocode
for ((name, value) <- instance.getClassProperties.getValues) {
case value.isInstanceOf[String] : map.push(name, value)
case _ : map.push(name, value.toString)
}
map
}
Run Code Online (Sandbox Code Playgroud)
那可能吗 ?如果你有很好的例子/链接,我很感兴趣.
Nik*_*kov 21
是的,这是可能的.从Scala 2.10开始,您可以使用反射.
假设你有:
val test = Test(23423, "sdlkfjlsdk")
Run Code Online (Sandbox Code Playgroud)
以下内容将为您提供所需内容:
import reflect.runtime.universe._
import reflect.runtime.currentMirror
val r = currentMirror.reflect(test)
r.symbol.typeSignature.members.toStream
.collect{case s : TermSymbol if !s.isMethod => r.reflectField(s)}
.map(r => r.symbol.name.toString.trim -> r.get.toString)
.toMap
Run Code Online (Sandbox Code Playgroud)
简单地迭代.productIterator在其实例上使用案例类的字段值.
Edm*_*984 11
您正在处理的主题在StackOverFlow上变得令人难以置信,如果您想要一个类型安全的实现,问题并不是微不足道的.
解决问题的一种方法是使用反射(如建议的那样),但我个人更喜欢使用类型系统和暗示.
有一个着名的库,由一个非常聪明的人开发,它允许你执行高级操作,例如将任何案例类转换为类型安全的异构列表,或者创建可用于实现"可扩展记录"的异常映射.该库名为Shapeless,这里有一个例子:
object RecordExamples extends App {
import shapeless._
import HList._
import Record._
object author extends Field[String] { override def toString = "Author" }
object title extends Field[String] { override def toString = "Title" }
object id extends Field[Int] { override def toString = "ID" }
object price extends Field[Double] { override def toString = "Price" }
object inPrint extends Field[Boolean] { override def toString = "In print" }
def printBook[B <: HList](b : B)(implicit tl : ToList[B, (Field[_], Any)]) = {
b.toList foreach { case (field, value) => println(field+": "+value) }
println
}
val book =
(author -> "Benjamin Pierce") ::
(title -> "Types and Programming Languages") ::
(id -> 262162091) ::
(price -> 44.11) ::
HNil
printBook(book)
// Read price field
val currentPrice = book.get(price) // Static type is Double
println("Current price is "+currentPrice)
println
// Update price field, relying on static type of currentPrice
val updated = book + (price -> (currentPrice+2.0))
printBook(updated)
// Add a new field
val extended = updated + (inPrint -> true)
printBook(extended)
// Remove a field
val noId = extended - id
printBook(noId)
}
Run Code Online (Sandbox Code Playgroud)
Book的行为类似于可以使用对象作为键索引的类型安全映射.如果您有兴趣了解更多信息,可能会有一个很好的切入点: