gpt4 book ai didi

斯卡拉 2.10 : Dynamically instantiating case classes

转载 作者:行者123 更新时间:2023-12-01 11:08:57 26 4
gpt4 key购买 nike

我有一个“动态实例化案例类”的梦想——并根据每个字段类型为字段提供一些虚拟数据(我稍后会为此创建一些规则)

到目前为止,我有一些代码可以与 String 的案例类一起使用; LongInt ... 如果有可能处理嵌入式案例类,我有点卡住了

所以我可以实例化case class RequiredAPIResponse (stringValue: String, longValue: Long, intVlaue: Int)

但不是外部; Outer 在哪里...

case class Inner (deep: String)
case class Outer (in : Inner)

代码是

 def fill[T <: Object]()(implicit mf: ClassTag[T]) : T = {

val declaredConstructors = mf.runtimeClass.getDeclaredConstructors
if (declaredConstructors.length != 1)
Logger.error(/*T.toString + */" has " + declaredConstructors.length + " constructors --- only 1 currently supported.")
val constructor = declaredConstructors.headOption.get

val m = constructor.getParameterTypes.map(p => {
Logger.info("getName " + p.getName +" --- getCanonicalName " + p.getCanonicalName)
Logger.info(p.getCanonicalName)

p.getCanonicalName match {
case "java.lang.String" => /*"Name"->*/ val s : java.lang.String = "DEFAULT STRING"
s
case "long" => /*"Name"-> */ val l : java.lang.Long = new java.lang.Long(99)
l
case "int" => /*"Name"->*/ val i : java.lang.Integer = new java.lang.Integer(99)
i
case _ => /*"Name"->*/

So around here I am stuck!
//THIS IS MADE UP :) But I want to get the "Type" and recursively call fill
//fill[p # Type] <- not real scala code

//I can get it to work in a hard coded manner
//fill[Inner]

}
})

我感觉像是Scala: How to invoke method with type parameter and manifest without knowing the type at compile time?上的最后一个答案是答案的起点。所以不要使用 T <: Object; fill 应该采用 ClassTag 还是 TypeTag?

此代码从 - How can I transform a Map to a case class in Scala? 开始- 其中提到(正如 Lift-Framework 所做的那样)我确实有 liftweb 源代码;但迄今为止未能解开其所有 secret 。

编辑 --- 根据 Imm 的观点,我可以使用以下代码(对他的回答进行一些小更新)

def fillInner(cls: Class[_]) : Object = {
val declaredConstructors = cls.getDeclaredConstructors
if (declaredConstructors.length != 1)
Logger.error(/*T.toString + */ " has " + declaredConstructors.length + " constructors --- only 1 currently supported.")
val constructor = declaredConstructors.headOption.get

val m = constructor.getParameterTypes.map(p => {
Logger.info("getName " + p.getName + " --- getCanonicalName " + p.getCanonicalName)
Logger.info(p.getCanonicalName)

p.getCanonicalName match {
case "java.lang.String" => /*"Name"->*/ val s: java.lang.String = "DEFAULT STRING"
s
case "long" => /*"Name"-> */ val l: java.lang.Long = new java.lang.Long(99)
l
case "int" => /*"Name"->*/ val i: java.lang.Integer = new java.lang.Integer(99)
i
case _ => fillInner(p)
}

})

constructor.newInstance(m: _*).asInstanceOf[Object]

}

def fill[T](implicit mf: ClassTag[T]) : T = fillInner(mf.runtimeClass).asInstanceOf[T]

谢谢,布伦特

最佳答案

你实际上并没有使用 ClassTag,只是 Class[_],而且这些都不是类型安全的(它只是 Java 反射),所以只需传递Class[_] 递归:

def fillInner(cls: Class[_]) : Any = {
val declaredConstructors = cls.getDeclaredConstructors
if (declaredConstructors.length != 1)
Logger.error(/*T.toString + */" has " + declaredConstructors.length + " constructors --- only 1 currently supported.")
val constructor = declaredConstructors.headOption.get

val m = constructor.getParameterTypes.map(p => {
Logger.info("getName " + p.getName +" --- getCanonicalName " + p.getCanonicalName)
Logger.info(p.getCanonicalName)

p.getCanonicalName match {
case "java.lang.String" => /*"Name"->*/ val s : java.lang.String = "DEFAULT STRING"
s
case "long" => /*"Name"-> */ val l : java.lang.Long = new java.lang.Long(99)
l
case "int" => /*"Name"->*/ val i : java.lang.Integer = new java.lang.Integer(99)
i
case _ => fillInner(p)
}
})

def fill[T: ClassTag]: T = fillInner(classOf[T].runtimeClass).asInstanceOf[T]

但是您可能可以通过使用 Shapeless 以类型安全的方式完成您想做的事情:

trait Supplier[T] {
def supply: T
}
object Supplier[T] {
implicit val intSupplier = new Supplier[Int] {
def supply = 99
}
implicit val stringSupplier = ...
implicit val emptyHListSupplier = new Supplier[HNil] {
def supply = HNil
}
implicit def consHListSupplier[H, T <: HList](
implicit headSupplier: Supplier[H],
tailSupplier: Supplier[T]) = new Supplier[H :: T] {
def supply = headSupplier.supply :: tailSupplier.supply
}
}

然后通过隐式解析的魔力,您可以获得 Supplier[(String::HNil)::Int::HNil] 或任何递归 HList HList 最终只包含您拥有 Supplier 的值;你只需要更无形的东西(在版本 1 或 2 中有所不同,我已经有一段时间没做过了,所以我不记得具体细节了)在这些和案例类之间来回转换。

关于斯卡拉 2.10 : Dynamically instantiating case classes,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27823448/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com