samedi 28 novembre 2015

Using Scala reflection to check for a method on an object or to find key type on a Map

I am porting a class from Ruby to Scala 2.11 that implements variable merging in messages. I would like to pass an array of objects to the merge method and have it search each object for the keys that are referenced in the text of the message.

The core of this is a method called lookUp(key: String, obj: AnyRef) which receives a single key for which to search, and a single object on which to search for the key. If the object is a Map, and the Map's keys are either Symbol or String, then it will look in the Map for the requested key. Otherwise it will check if the object has a method with the same name of the key, and if so, it will invoke that method.

In the existing Ruby code, it is trivially easy to do this:

def look_up(key, obj)
  if obj.respond_to?(:has_key?) && obj.has_key?(key)
    obj[key]
  elsif obj.respond_to?(key)
    obj.send(key)
  elsif obj.instance_variable_defined?(ivar = "@#{key}")
    obj.instance_variable_get(ivar)
  end
end

Since it's easy to do so, the Ruby code also looks for an instance variable of the same name. I don't necessarily need that functionality in my Scala version.

One of the issues I am having is that the examples I've found require that I know the object's class ahead of time so I can call ru.typeOf[MyClass].declaration(ru.TermName("key")) (where ru is scala.reflect.runtime.universe).

Another issue is that this message merge can be happening hundreds of times per minute, and reflection seems to be a slow, involved process. If this all works as planned, I'll likely cache the reflection results by object type.





Aucun commentaire:

Enregistrer un commentaire