2016-11-25 86 views
4

當試圖通過字符串名稱獲取對象字段時,返回的值不是正確的scala類型。正如:如何根據字符串名稱和原始類型來獲取字段值的反射

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

不知道,一個人如何可以從一個單一的函數返回不同的類型。 但是你可以使用scala反映api(s)來推斷任何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") 
相關問題