Need some guidance on how to use reflection to do dynamic property access of a case class

182 views
Skip to first unread message

John Arrowwood

unread,
Apr 19, 2016, 4:10:34 PM4/19/16
to scala-user
I want to simulate dynamic programming.  The reason has to do with wanting to avoid doing the same thing dozens or even hundreds of times, as that tends to get tedious and error prone.

Given something like this:

trait SymbolicAccess {
 
def get[T]( field : scala.Symbol ) = { /* equivalent of this.[field] */ }
 
def set[T]( field : scala.Symbol, value : T ) = { /* reflection equivalent of (this.[field] = value) */ }
}

case class Foo
(
  val one
: String,
  val two
: Long,
  val three
: Boolean
)
extends SymbolicAccess

I am going to iterate over the fields in the class, and for every field that matches some conditions, do something with it.  The iteration and filtering is based on data stored in the companion object, and I have that working.  The only thing left is to get the definition of trait SymbolicAccess right.  

The reflection API is a bit daunting to me, and the docs I have read so far feel a bit like trying to teach me how to build a clock when all I want to know is what time it is.  I'm trying to sift through it, but if someone can give me some tips to help me focus my reading, or even a bit of sample code, it would be appreciated.

Balamanikandan T

unread,
Apr 26, 2016, 5:56:33 AM4/26/16
to scala-user

Hi John

  I would like to share what i know. 

object HelloWorld {

    def main(args: Array[String]) = {
     val s = Foo.set("Bala", 1000, true)   
     
     println("Hello Scala!")
        // get class fields like that "val field = ClassName.fieldName"            
        println(s.one)   
        println(s.two)   
        println(s.three)   
    }
    
    //DAO
    object Foo{        
       def set(a:String, b:Long, c:Boolean) = Foo(a, b, c)        
    }
    
    // case class
    case class Foo(
      one : String,
      two : Long,
      three : Boolean
    )    
}


Result:

Hello Scala!
Bala
1000
true


Lutz Huehnken

unread,
Apr 26, 2016, 6:13:14 AM4/26/16
to scala-user
Hi John,

Have you looked at http://www.scala-lang.org/api/2.11.8/#scala.Dynamic ? Maybe instead of implementing get/set you could just leverage selectDynamic / updateDynamic? Also see http://stackoverflow.com/a/15799812/52055

Hope this helps,
Lutz

Dmitriy Kostyuchenko

unread,
Apr 26, 2016, 2:44:23 PM4/26/16
to scala-user
You can also do this in a type-safe way at compile time without reflection by using shapeless.

@ import shapeless._, record._ 
import shapeless._, record._

@ case class Foo(one: String, two: Long, three: Boolean) 
defined class Foo

@ val fooGeneric = LabelledGeneric[Foo] 
fooGeneric: LabelledGeneric[Foo]{type Repr = shapeless.::[String with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("one")],String],shapeless.::[Long with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("two")],Long],shapeless.::[Boolean with shapeless.labelled.KeyTag[Symbol with shapeless.tag.Tagged[String("three")],Boolean],shapeless.HNil]]]} = shapeless.LabelledGeneric$$anon$1@289254fe

@ val fooInst = Foo("One", 2L, true) 
fooInst: Foo = Foo("One", 2L, true)

@ val genFooInst = fooGeneric.to(fooInst) 
genFooInst: fooGeneric.Repr = One :: 2 :: true :: HNil

@ genFooInst('one) 
res12: String = "One"

@ genFooInst('three) 
res13: Boolean = true


Reply all
Reply to author
Forward
0 new messages