2014-01-13 3 views
1

Я хотел бы спросить, как достичь следующего в Scala. РассмотримВ Scala, полученное значение объявленного поля, отлитого от класса, объявленного классом

scala> case class C(i:Int) 
defined class C 

scala> val c = C(1) 
c: C = C(1) 

Учитывая поле интересов, в данном случае

scala> val fname = "i" 
fname: String = i 

мы хотели бы получить первоначальное значение и тип поля я в с.

Первая, наивная попытка включала следующее,

scala> val f = c.getClass.getDeclaredField(fname) 
f: java.lang.reflect.Field = private final int C.i 

scala> f.setAccessible(true) 

scala> f.getType 
res3: Class[_] = int 

Однако

scala> val a:Int = f.get(c) 
<console>:11: error: type mismatch; 
found : Object 
required: Int 
     val a:Int = f.get(c) 
         ^

Другими словами, как получить значение Int для г в с (*)

scala> :type -v case class C(i:Int) 
// Type signature 
AnyRef 
     with Product 
     with Serializable { 
    val i: Int <----------------------- (*) 
    private[this] val i: Int 
    def <init>(i: Int): C 
    def copy(i: Int): C 
... 

и не обязательно тип Int, рассмотрите поле j в D,

scala> case class C(i:Int) 
defined class C 

scala> case class D(j:C) 
defined class D 

scala> :type -v case class D(j:C) 
// Type signature 
AnyRef 
     with Product 
     with Serializable { 
    val j: C 
    private[this] val j: C 
    def <init>(j: C): D 
    def copy(j: C): D 
... 

Большое спасибо ...

В сводке

Учитывая

scala> f.get(c) 
res1: Object = 1 

и

scala> f.getType 
res3: Class[_] = int 

как получить

val a = 1 

где a имеет тип Int и знает тип только из f.getType.

+1

Как вы могли ожидать, что он будет работать без актерского состава, если вы используете отражение, чтобы получить его ценность? Компилятор не имеет понятия о типе поля с именем «i» (и не существует ли он на самом деле). –

ответ

2

статический типf.get(c) - Object, так как это может быть любой класс и любое поле. Однако во время выполнения он вернет Integer (класс оболочки Java для Int). Вы можете бросить его с помощью

f.get(c).asInstanceOf[Int] 

или

f.getInt(c) 

, если вы знаете заранее, что вы вызываете для Int поля. Если вы этого не сделаете, вы можете шаблон матча:

f.get(c) match { 
    case i: Integer => ... 
    case s: String => ... 
    // etc. 
} 

или получить его тип с f.getType.

+0

Большое спасибо, Алексей; в этом случае, однако, тип будет _inferrable_ только из объявления класса ... – elm

+0

Вызов 'f.getType' поставляет' Class [_] = int'; следовательно, как бросить его на Int. – elm

+0

С 'asInstanceOf', как сказано. –

Смежные вопросы