I'm trying to figure out how to invoke a constructor for a Scala abstract type:
class Journey(val length: Int)
class PlaneJourney(length: Int) extends Journey(length)
class BoatJourney(length: Int) extends Journey(length)
class Port[J <: Journey] {
def startJourney: J = {
new J(23) // error: class type required but J found
}
}
Is this even feasible? I'm familiar with Scala manifests but I'm not clear how they could help here. Likewise I can't figure out how to do the same with a companion object's apply() constructor:
object Journey { def apply() = new Journey(0) }
object PlaneJourney { def apply() = new PlaneJourney(0) }
object BoatJourney { def apply() = new BoatJourney(0) }
class Port[J <: Journey] {
def startJourney: J = {
J() // error: not found: value J
}
}
Any thoughts gratefully received!
There is no direct way to invoke the constructor or access the companion object given only a type. One solution would be to use a type class that constructs a default instance of the given type.
trait Default[A] { def default: A }
class Journey(val length: Int)
object Journey {
// Provide the implicit in the companion
implicit def default: Default[Journey] = new Default[Journey] {
def default = new Journey(0)
}
}
class Port[J <: Journey : Default] {
// use the Default[J] instance to create the instance
def startJourney: J = implicitly[Default[J]].default
}
You will need to add an implicit Default definition to all companion objects of classes that support creation of a default instance.
Your class needs an implicit constructor parameter to get the Manifest. Then you can call erasure to get the Class and call newInstance, which reflectively calls the nullary constructor if there is one.
class J[A](implicit m:Manifest[A]) {
def n = m.erasure.newInstance()
}
new J[Object].n
As of Scala 2.10, the erasure property in the manifest is deprecated. def n = m.runtimeClass.newInstance() does the same thing, but without warnings.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With