Get companion object of class by given generic type Scala
I keep hitting this page when I forget how to do this and the answers are not hundred percent satisfactory for me. Here is how I do with reflection:
val thisClassCompanion = m.reflect(this).symbol.companion.asModule
val structural = m.reflectModule(thisClassCompanion)
.instance.asInstanceOf[{def doSth: Unit}]
You might need to verify that the class actually has a companion object or companion.asModule will throw a reflection exception is not a module
Updated: added another example for clarity:
object CompanionUtil {
import scala.reflect.runtime.{currentMirror => cm}
def companionOf[T, CT](implicit tag: TypeTag[T]): CT = {
Try[CT] {
val companionModule = tag.tpe.typeSymbol.companion.asModule
cm.reflectModule(companionModule).instance.asInstanceOf[CT]
}
}.getOrElse(throw new RuntimeException(s"Could not get companion object for type ${tag.tpe}"))
}
You could use reflection to get the companion class and its instance, but that relies on Scala internals that might change in some far(?) future. And there is no type safety as you get an AnyRef. But there is no need to add any implicits to your classes and objects.
def companionOf[T : Manifest] : Option[AnyRef] = try{
val classOfT = implicitly[Manifest[T]].erasure
val companionClassName = classOfT.getName + "$"
val companionClass = Class.forName(companionClassName)
val moduleField = companionClass.getField("MODULE$")
Some(moduleField.get(null))
} catch {
case e => None
}
case class A(i : Int)
companionOf[A].collect{case a : A.type => a(1)}
// res1: Option[A] = Some(A(1))
Based on the answer by Miquel, here's a method that gets the type reference of the companion object of the specified class object:
/**
* Returns the companion object type reference for the specified class
*
* @param clazz The class whose companion is required
* @tparam CT Type of the companion object
* @return The type of the relevant companion object
*/
def companionOf[CT](clazz: Class[_]): CT = {
import scala.reflect.runtime.{currentMirror => cm}
Try[CT] {
val companionModule = cm.classSymbol(clazz).companion.asModule
cm.reflectModule(companionModule).instance.asInstanceOf[CT]
}.getOrElse(throw new RuntimeException(s"Could not get companion object for $clazz"))
}
A gist by Miles Sabin may give you a hint:
trait Companion[T] {
type C
def apply() : C
}
object Companion {
implicit def companion[T](implicit comp : Companion[T]) = comp()
}
object TestCompanion {
trait Foo
object Foo {
def bar = "wibble"
// Per-companion boilerplate for access via implicit resolution
implicit def companion = new Companion[Foo] {
type C = Foo.type
def apply() = Foo
}
}
import Companion._
val fc = companion[Foo] // Type is Foo.type
val s = fc.bar // bar is accessible
}
This should be compiled with the -Ydependent-method-types
flag if using Scala 2.9.x.