mercredi 14 juin 2023

Get companion object (declared in an inner class) of generic type without instance

I am working on a method which is given only one piece of information: a type that extends ClassTag (this can be changed to TypeTag if strong guarantees are necessary for resolving certain parts of the type). We are not given an instance such that we can use scala.reflect.runtime.currentMirror to obtain a InstanceMirror from the Scala libraries available. We are not given the arguments necessary to construct such an instance. I am only able to obtain a RuntimeClass of this generic type. Scala has the concept of a companion object. I want to check if the companion object of the given generic class T extends a specific trait A, cast that object as that trait, and invoke the method which is overriden by that companion object. The current code to do what I described is below:

def invokeOverridenMethodOfCompanionObject[T : ClassTag]() {
  import scala.reflect.runtime.currentMirror
  import scala.reflect.runtime.universe.NoSymbol

  val runtimeClass = scala.reflect.classTag[T].runtimeClass
  val companion = currentMirror.classSymbol(runtimeClass).companion

  companion match {
    case NoSymbol => // do nothing
    case _ => 
      // The problem is this line
      currentMirror.reflectModule(companion.asModule).instance match {
        case s: A => s.invokeOverridenMethod
        case _ => // do nothing 
      }
  }
}

This approach is almost perfect. The problem is that if the object is not top level i.e. declared within another object or class, this method no longer works. Scala then complains and spits out this error:

object <objectName> is an inner module, use reflectModule on an InstanceMirror to obtain its ModuleMirror

The problem is I am not able to obtain the instance mirror of the symbol/type which owns the companion object. I cannot construct that instance either since I have no arguments to build a dummy constructor either. I also cannot guarantee the existence of a nullary constructor either, so gimmicks using them are off limits as well. Is there a way to accomplish my goal given these constraints?

Edit: I am aware that Java Class can allow a person to search up the method by name and then invoke it. I know this is possible but my solution would require passing around the object later as well. Therefore, it is a must for me to obtain a variable reference directly to the object. You may assume that after the code block above ends, I return the companion object constructed.





Aucun commentaire:

Enregistrer un commentaire