david.perez
david.perez

Reputation: 7032

How to use reflection at compile time

I have this situation:

class Column {
}

trait Table {
    lazy val columns: List[Column] = ....
}

class MyTable extends Table {
   val column1 = new Column()
   val column2 = new Column()
}

I would like to get the list of columns defined in derived classes at compile time.

I've already been able to do by using runtime reflection, but I've heard that it can be problematic in Android and ProGuard. So, I'd like to do it at compile time if possible.

https://groups.google.com/forum/#!topic/scala-on-android/Q0E_OMYqE0A

Here is my implementation with runtime reflection:

trait Table {
    lazy val columns: List[Column] = {
        import scala.reflect.runtime.universe._
        val rm = scala.reflect.runtime.currentMirror
        val columns = rm.classSymbol(this.getClass).toType.members.collect {
            case m: MethodSymbol if m.isGetter && m.returnType <:< typeOf[Column] => m
        }
        val espejo = rm.reflect(this)
        (for (col <- columns) yield
            espejo.reflectMethod(col).apply().asInstanceOf[Column]).toList
    }    
}

Upvotes: 5

Views: 2489

Answers (1)

johanandren
johanandren

Reputation: 11479

You could do this with a Scala "def macro2 in Scala 2.10 and higher. A def macro is essentially a function that will get called during compilation with the AST (abstract syntax tree) of the parameters given to the function, that function will then also return an AST that the compiler will put in place of the call to the macro.

You can read more about it here: http://docs.scala-lang.org/overviews/macros/overview.html

Upvotes: 2

Related Questions