Why wouldn\'t the scala compiler dig this:
class Clazz
class Foo[C <: Clazz] {
val foo = new C
}
class type required but C found
[error] val a = new C
I came up with this scheme, couldn't simplify it through a companion object thought.
class Clazz
class ClazzFactory {
def apply = new Clazz
}
class Foo(factory: ClazzFactory) {
val foo: Clazz = factory.apply
}
It's very annoying that ClazzFactory can't be an object rather than a class though. A simplified version:
class Clazz {
def apply() = new Clazz
}
class Foo(factory: Clazz) {
val foo: Clazz = factory.apply
}
This requires the caller to use the new keyword in order to provide the factory argument, which is already a minor enough annoyance relative to the initial problem. But, scala could have made this scenario all more elegant; I had to fallback here to passing a parameter of the type I wish to instantiate, plus the new
keyword. Maybe there's a better way.
(motivation was to instantiate that type many times within the real Foo
, that's why this is at all a solution; otherwise my pattern above is just redundantly meaningless).
This is a classic generic problem that also happens in Java - you cannot create an instance of a generic type variable. What you can do in Scala to fix this, however, is to introduce a type evidence to your type parameter that captures the runtime type:
class Foo[C <: Clazz](implicit ct: ClassTag[C]) {
val foo = ct.runtimeClass.newInstance
}
Note that this only works if the class has a constructor without any arguments. Since the parameter is implicit, you don't need to pass it when calling the Foo constructor:
Foo[Clazz]()