2012-02-07 28 views
25

私がやろうとしているのはジェネリッククラスを取り、その中に静的メソッドを使う関数を作ることです(Java言語では申し訳ありません、 )。与えられたジェネリック型のクラスのコンパニオンオブジェクトを取得する

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 
} 

答えて

20

A gist by Miles Sabinはあなたにヒントを与えることがあります。

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 
} 

Scalaの2.9.x.を使用した場合、これは-Ydependent-method-typesフラグを指定してコンパイルする必要があります

+0

私は実際のGistの内容を追加しました.Gistは消えるかもしれませんし、リンクだけでコメントになるかもしれません。 –

+0

エラー:不正な従属メソッドのタイプ 暗黙のdef companion [T](暗黙のcomp:Companion [T])= comp.apply() T])= comp() "とスカラー2.9.1。私はそれを間違っているのですか? :-) –

+3

私は括弧書きで、 'Foo'の型が見えるならばそれはコンパニオンオブジェクトなので、これはかなり気になりますが実際には役に立たないと思います。 –

7

リフレクションを使用してコンパニオンクラスとそのインスタンスを取得できますが、これは遠くの(?)将来変更される可能性のあるScala内部構造に依存します。 AnyRefを取得すると型の安全性はありません。しかし、クラスやオブジェクトに暗黙の記述を追加する必要はありません。

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)) 
+0

ありがとう、リフレクションは問題を解決します...スカラバージョンの更新まで、コンパニオンオブジェクトの名前はこのように保たれると約束されていません。 –

+1

まあ、それは本当です。しかし、このコンベンションはScala 2.xの初期の段階から少なくとも継続されていたので、すぐに名前が変わるとは思っていません。 – MxFr

関連する問題