2016-10-19 158 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和訪問欄:

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) 

這應該打印出「5」和「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

我認爲你應該使用'scala.reflect.ClassTag'而不是'TypeTag'。 –

+0

你真的想讓'createInstance'擁有自己的'T'類型參數嗎,不同於'Foo'嗎? –

回答

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 extends Foo [X] yFoo extends Foo [Y] –

相關問題