我试图弄清楚如何为Scala抽象类型调用构造函数:
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
}
}
这甚至可行吗?我熟悉Scala manifests,但我不清楚他们如何在这里提供帮助。同样,我无法弄清楚如何使用伴随对象的apply()构造函数来做同样的事情:
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
}
}
感激地收到任何想法!
答案 0 :(得分:7)
您的类需要一个隐式构造函数参数来获取Manifest
。然后你可以调用erasure来获取Class
并调用newInstance
,如果有的话,它会反过来调用nullary构造函数。
class J[A](implicit m:Manifest[A]) {
def n = m.erasure.newInstance()
}
new J[Object].n
从Scala 2.10开始,不推荐使用清单中的erasure
属性。 def n = m.runtimeClass.newInstance()
做同样的事情,但没有警告。
答案 1 :(得分:7)
没有直接的方法来调用构造函数或仅在给定类型的情况下访问伴随对象。一种解决方案是使用构造给定类型的默认实例的类型类。
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
}
您需要向支持创建默认实例的类的所有伴随对象添加隐式Default
定义。
答案 2 :(得分:0)
我的倾向是,这是无法做到的。我离斯卡拉大师很远,但我的理由是这样的:
这个问题的解决方案在另一个问题上得到了很好的处理,所以我会在那里指出你而不是在这里重复:Abstract Types / Type Parameters in Scala