2016-11-25 22 views
4

文字列名でオブジェクトフィールドを取得しようとすると、正しいスカラ型ではなく値が返されます。よう:文字列名と元の型でフィールド値を取得するためのリフレクションを作成する方法

import scala.language.reflectiveCalls 
import scala.language.implicitConversions 

case class Intity(flag: Boolean, id: Int, name: String) 
val inty = Intity(false, 123, "blue") 

implicit def reflect(r: AnyRef) = new { 
    def get(n:String) = { 
    val c = r.getClass.getDeclaredField(n) 
    c.setAccessible(true); c} 
    def getVal(n: String) = get(n).get(r) 
    def getType (n:String) = get(n).getType 
} 

この

を使用して
inty.getType("flag")  // res0: Class[_] = boolean --not Boolean 
inty.getVal("id")  // res1: Object = 123 --Object not Int 

上記の実装を行うための任意の効率的な方法?

+0

代わりの反射、[不定形](https://github.com/milessabin/shapeless)があなたの問題を解決することができるだろうか? – Reactormonk

+0

@Reactormonkしかし、どのように、私はこれまで不運についてはあまり知らない。文字列名によるクラス属性へのアクセスをサポートし、元の型で値を返しますか? – ALMEK

+1

実行時リフレクションを使用してコンパイル時に正確な型を取得することはありません。それについて考える。 –

答えて

1

シェイプレスでコンパイル時に同様のことを行うことができます。

scala> import shapeless._ 
import shapeless._ 

scala> val inty = Intity(false, 123, "blue") 
inty: Intity = Intity(false,123,blue)   

scala> val intyGen = LabelledGeneric[Intity].to(inty) 
intyGen: shapeless.::[Boolean with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("flag")],Boolean],shapeless.::[Int with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("id")],Int],shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("name")],String],shapeless.HNil]]] = false :: 123 :: blue :: HNil 

scala> import shapeless.record._ 
import shapeless.record._ 

scala> intyGen.get('flag) 
res10: Boolean = false 

scala> intyGen.get(Symbol("id")) 
res11: Int = 123 
5

どのようにして1つの関数からさまざまな型を返すかわかりません。 しかし、scalaを反映したAPIを使って、正しいタイプのClass属性を推論することができます。

import scala.reflect.runtime.{universe => ru} 
implicit class ForAnyInstance[T: ru.TypeTag](i: T)(implicit c: scala.reflect.ClassTag[T]) { 

    /* a mirror sets a scope of the entities on which we have reflective access */ 
    val mirror = ru.runtimeMirror(getClass.getClassLoader) 

    /* here we get an instance mirror to reflect on an instance */ 
    val im = ru.runtimeMirror(i.getClass.getClassLoader) 

    def fieldInfo(name: String) = { 
     ru.typeOf[T].members.filter(!_.isMethod).filter(_.name.decoded.trim.equals(name)).foreach(s => { 
     val fieldValue = im.reflect(i).reflectField(s.asTerm).get 

     /* typeSignature contains runtime type information about a Symbol */ 
     s.typeSignature match { 
      case x if x =:= ru.typeOf[String] => /* do something */ 
      case x if x =:= ru.typeOf[Int] => /* do something */ 
      case x if x =:= ru.typeOf[Boolean] => /* do something */ 
     } 
     }) 
    } 
} 

そしてとしてそれを呼び出す:

case class Entity(flag: Boolean, id: Int, name: String) 
val e = Entity(false, 123, "blue") 
e.fieldInfo("flag") 
e.fieldInfo("id") 
関連する問題