2

私がやろうとしていることは本当に単純なはずです。おもう。リフレクションを使用して、ケース クラス コンストラクターへの引数の名前と型を決定したいと考えています。以下はREPLの相互作用です。「paramss」が呼び出される最後までスキップできます。「名前」が実際に文字列であり、「年齢」が Int であることを確認するために、内側のリストのシンボルと照合またはパターン マッチを行いたいと考えています。

それ、どうやったら出来るの?

scala> case class Person(name: String, age: Int)
defined class Person

scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._

scala> typeOf[Person]
res0: reflect.runtime.universe.Type = Person

scala> typeTag[Person]
res1: reflect.runtime.universe.TypeTag[Person] = TypeTag[Person]

scala> res1.mirror
res2: reflect.runtime.universe.Mirror = JavaMirror with scala.tools.nsc.interpreter.IMain$TranslatingClassLoader@2daf73a4 of type class scala.tools.nsc.interpreter.IMain$TranslatingClassLoader with classpath [(memory)] and parent being scala.tools.nsc.util.ScalaClassLoader$URLClassLoader@59d12b6a of type class scala.tools.nsc.util.ScalaClassLoader$URLClassLoader with classpath [file:/Library/Java/JavaVirtualMachines/jdk1.7.0_13.jdk/Contents/Home/jre/lib/resources.jar,file:/Library/Java/JavaVirtualMachines/jdk1.7.0_13.jdk/Contents/Home/jre/lib/rt.jar,file:/Library/Java/JavaVirtualMachines/jdk1.7.0_13.jdk/Contents/Home/jre/lib/jsse.jar,file:/Library/Java/JavaVirtualMachines/jdk1.7.0_13.jdk/Contents/Home/jre/lib/jce.jar,file:/Library/Java/JavaVirtualMachines/jdk1.7.0_13.jdk/Contents/Home/j...
scala> res1.tpe
res3: reflect.runtime.universe.Type = Person

scala> res3.typeSymbol.asClass
res4: reflect.runtime.universe.ClassSymbol = class Person

scala> res2.reflectClass(res4)
res5: reflect.runtime.universe.ClassMirror = class mirror for Person (bound to null)

scala> res3.declaration(reflect.runtime.universe.nme.CONSTRUCTOR)
res6: reflect.runtime.universe.Symbol = constructor Person

scala> res6.asMethod
res7: reflect.runtime.universe.MethodSymbol = constructor Person

scala> res7.paramss
res8: List[List[reflect.runtime.universe.Symbol]] = List(List(value name, value age))
4

3 に答える 3

1

Typeこれが、コンストラクタ パラメータの型を表すオブジェクトを取得する方法です。

val ctorParamss = typeOf[Person].member(nme.CONSTRUCTOR).asMethod.paramss
val typeOfNameParam: Type = paramss(0)(0).typeSignature

オブジェクトを取得したので、さまざまなテストを実行できます。

typeOfNameParam =:= typeOf[Int]      // is this type an Int ?
typeOfNameParam <:< typeOf[Number]   // is this type java.lang.Number or its subtype ?
于 2013-04-01T12:24:42.030 に答える
1

SMirror の使用:

scala> import net.fwbrasil.smirror._
import net.fwbrasil.smirror._

scala> implicit val mirror = scala.reflect.runtime.currentMirror
mirror: reflect.runtime.universe.Mirror = JavaMirror with scala.t...

scala> case class Person(name: String, age: Int)
defined class Person

scala> val clazz = sClassOf[Person]
clazz: net.fwbrasil.smirror.SClass[Person] = Person

scala> val ctor = clazz.constructors.head
ctor: net.fwbrasil.smirror.SConstructor[Person] = <init>(name: java.lang.String, age: scala.Int): Person

scala> ctor.parameters
res0: List[ctor.SParameterType] = List(name: java.lang.String, age: scala.Int)

scala> ctor.parameters.head.sClass == sClassOf[String]
res2: Boolean = true
于 2013-04-01T14:03:59.780 に答える
0

あなたが尋ねるべき面白い!これはまさに私が今やっていることです。

まず、paramss があります。そのため、複数のパラメーター リストをサポートする方法/サポートするかどうかに対処する必要があります。正確に 1 つのパラメーター リストを要求し、それをキャプチャするコードを次に示します。

val ctorParams  : List[Symbol] = ctorParamss match {
  case Nil => {
println("Warning: Trying to populate a no-arg constructor from a Map. No data will be used.");
Nil;
  }
  case head :: Nil => head;
  case _ => throw new UnsupportedOperationException("Cannot populate a constructor with multiple param lists from a Map.");
}

次に、名前と型名が必要です。

val ctorParamNames = ctorParams.map( _.name.toString.trim );
val ctorParamTypeNames = ctorParams.map( _.typeSignature.baseClasses(0).fullName.toString.trim );

私はまだこれに取り組んでいますが、これはまさにこの瞬間ですが、これまでのところ私にとってはうまくいっています。幸運を!

于 2013-04-01T06:05:16.240 に答える