传递类型参数以进行实例化

时间:2015-09-26 13:29:36

标签: scala

为什么scala编译器不会这样做:

class Clazz

class Foo[C <: Clazz] {
  val foo = new C  
}

class type required but C found
[error]   val a = new C
[error]               ^

相关问题 - How to get rid of : class type required but T found

2 个答案:

答案 0 :(得分:2)

这是一个经典的通用问题,也发生在Java中 - 您无法创建泛型类型变量的实例。但是,您可以在Scala中解决此问题的方法是在类型参数中引入一个类型证据来捕获运行时类型:

class Foo[C <: Clazz](implicit ct: ClassTag[C]) {
    val foo = ct.runtimeClass.newInstance
}

请注意,这仅适用于类具有不带任何参数的构造函数的情况。由于参数是隐式的,因此在调用Foo构造函数时不需要传递它:

Foo[Clazz]()

答案 1 :(得分:0)

我想出了这个方案,无法通过伴侣对象思想来简化它。

class Clazz
class ClazzFactory {
  def apply = new Clazz
}

class Foo(factory: ClazzFactory) {
  val foo: Clazz = factory.apply
}

但是ClazzFactory不能成为一个对象而不是一个类,这非常令人讨厌。简化版本:

class Clazz {
  def apply() = new Clazz
}

class Foo(factory: Clazz) {
  val foo: Clazz = factory.apply
}

这要求调用者使用new关键字来提供工厂参数,这相对于初始问题已经是一个足够小的烦恼。但是,scala可以让这个场景变得更加优雅;我不得不回到这里传递我想要实例化的类型的参数,加上new关键字。也许有更好的方法。

(动机是在真实Foo内多次实例化那种类型,这就是为什么这完全是一个解决方案;否则我上面的模式只是多余无意义。)