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