Jay Taylor's notes

back to listing index

Get companion object of class by given generic type Scala - Stack Overflow

[web search]
Original source (stackoverflow.com)
Tags: scala manifests companion stackoverflow.com
Clipped on: 2012-09-25

What I am trying to do is to make a function that would take a generic class and use a static method in it (sorry for Java language, I mean method of its companion object).

trait Worker {def doSth: Unit}

class Base

object Base extends Worker

// this actually wouldn't work, just to show what I'm trying to achieve
def callSthStatic[T that companion object is <: Worker](implicit m: Manifest[T]) {
 
// here I want to call T.doSth (on T object)
  m
.getMagicallyCompanionObject.doSth
}

Any ideas?

edited Feb 7 at 8:06
Image (Asset 1/3) alt= 7,1971036
asked Feb 7 at 8:00
Image (Asset 2/3) alt= 376

86% accept rate
add comment

2 Answers

up vote 5 down vote accepted

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.

  upvote
 flag
I added the actual Gist contents - the Gist might disappear and the link alone qualifies as a comment. – Tomasz Nurkiewicz Feb 7 at 8:55
  upvote
 flag
I'm getting "error: illegal dependent method type implicit def companion[T](implicit comp : Companion[T]) = comp.apply()" at line "implicit def companion[T](implicit comp : Companion[T]) = comp()" with scala 2.9.1. Am I doing it wrong? :-) – Wojtek Erbetowski Feb 7 at 9:36
1 upvote
 flag
I'll add parenthetically that if the type Foo is visible then so is it's companion object, so although this looks quite nifty I don't think it's useful in practice. – Miles Sabin Feb 7 at 12:45
  upvote
 flag
That's a nice trick. I have to do some reading about dependent-method-types but this seem to work! Thanks – Wojtek Erbetowski Feb 10 at 14:51
add comment

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))
answered Feb 7 at 10:41
Image (Asset 3/3) alt= 912
  upvote
 flag
Thanks, reflection would solve the problem... until scala version update, as companion object's name is not promised to be kept this way. – Wojtek Erbetowski Feb 8 at 20:05
1 upvote
Well, thats true. But I dont think the naming would change any time soon, since this convention lasted at least since the early Scala 2.x days. – MxFr Feb 9 at 13:38
add comment

Your Answer

 
community wiki

Not the answer you're looking for? Browse other questions tagged or ask your own question.