2016-10-19 13 views
1

ジェネリック型パラメータを持つクラスがあり、このタイプのインスタンスをリフレクションを使用して作成したいと考えています。さらに、型には専用のコンストラクタがあります。ここ は、問題のコードサンプルです:Scala:プライベートコンストラクタを使用してジェネリック型からインスタンスを作成

class X private (x: Int) { 
} 
class Y private (y: Int) { 
} 
abstract class Foo[T](z : Int) { 
    var bar : T = createInstance[T](z) 
    def createInstance[T](z: Int) : M = { 
    ??? 
    } 
} 

これは私がfooとアクセスバーをインスタンス化することが可能になる:「5」

class xFoo extends Foo[X]{ 
} 

class yFoo extends Foo[Y]{ 
} 

var xfoo = new xFoo(5) 
println(xfoo.bar.x) 

var yfoo = new yFoo(6) 
println(yfoo.bar.y) 

これは、プリントアウトしなければならないと「6」。

私は以下の方法で暗黙的に使用しようとしました。

def createInstance[T](z: Int)(implicit tag: TypeTag[T]) : T = { 
    val clazz = tag.tpe.getClass 
    val ctor = class.getDeclaredConstructor(classOf[Int]) 
    ctor.setAccessible(true) 
    return ctor.newInstance(z).asInstanceOf[T] 
} 

はしかし、その後、私はエラーを取得する:

No TypeTag available for T 
ラインで

var bar : T = createInstance[T](z) 

任意の提案ですか?ご協力いただきありがとうございます!スーパークラスを使用するように探しているいくつかの方法/値を公開しないと仮定すると

+0

私はあなたが 'TypeTag'の代わりに' scala.reflect.ClassTag'を使うべきだと思います。 –

+0

'createInstance'が' Foo'とは違った 'T'型のパラメータを持つことを本当にしたいですか? –

答えて

1

class X private(val x: Int) {} 

あなたがそうのようにそれを拡張することができます。

import scala.reflect._ 

class Foo[T](z : Int)(implicit ct: ClassTag[T]) { 
    var bar : T = createInstance[T](z) 
    def createInstance[T](z: Int) : T = { 
    val ctor = ct.runtimeClass.getDeclaredConstructor(classOf[Int]) 
    ctor.setAccessible(true) 
    ctor.newInstance(Int.box(4)).asInstanceOf[T] 
    } 
} 

これは、呼び出すことができます:

class XFoo(n: Int) extends Foo[X](n) 
println((new XFoo(5)).bar.x) 
+0

ありがとうございますが、 –

+0

ありがとうございますが、行中にあります。 val ctor = classTag [X] .runtimeClass.getDeclaredConstructor(classOf [Int]) classTag [X]を使用しています。 これはclassTag [T]ですか? –

+0

申し訳ありませんが、私の質問は十分正確ではないと思います。抽象クラスFooは、型Tが異なるいくつかのクラスの基本クラスとして機能する必要があります。 xFooはFooを拡張します。 yFooはFoo [Y] –

関連する問題