对于Scala中的特征来说,Manifest上的访问似乎很棘手。
这段代码如何在scala中编译?
trait SomeTraitOf[+A] {
def newInstanceOfA : A = /* necessary code to make it work */
}
(相关,它作为参数化类可以正常工作:
class SomeTraitOf[A : Manifest] {
def newInstanceOfA(implicit m : Manifest[A]) : A =
m.erasure.newInstance.asInstanceOf[A]
}
但没有协变型参数(+ A))
编辑:真实的东西
sealed trait RootPeerProxy[+A] extends Proxy {
def peer: A
def self = peer
def peerManifest[B >: A](): Option[Manifest[B]]
private[scalavaadin] def newInstance() : Option[A]
}
trait PeerProxy[+A] extends RootPeerProxy[A] {
override def peerManifest[B >: A](): Option[Manifest[B]]
override def peer(): A = this.newInstance match {
case None => {throw new IllegalStateException("oups")}
case Some(a) => a
}
private[scalavaadin] override def newInstance() : Option[A] = peerManifest map { m => m.erasure.newInstance.asInstanceOf[A] }
}
由于traits不能为参数特征提供清单,实现特征的类应该,但我没有得到它。
答案 0 :(得分:4)
关于协方差:
由于Manifest[A]
在参数A
中不变,因此您无法直接执行所需操作。通常的策略是削弱回报类型,
trait SomeTraitOf[+A] {
def newInstance[B >: A](implicit m: Manifest[B]): B = {
m.erasure.newInstance.asInstanceOf[B]
}
}
您可以按如下方式使用特征
class Parent
class Child extends Parent
val childBuilder = new SomeTraitOf[Child] {}
val parentBuilder: SomeTraitOf[Parent] = childBuilder
parentBuilder.newInstance // returns a Parent!
关于查看边界:
从下面的评论中,我猜你也在询问“视图边界”,这只是一种声明隐式参数的简洁方法。你的声明
class SomeTraitOf[A : Manifest] { ...
基本上翻译为
class SomeTraitOf[A]()(implicit m0: Manifest[A]) { ....
Traits不能有视图边界,因为它们不能获取任何(值)参数。但这不是一个真正的问题,因为在你的例子中
class SomeTraitOf[A : Manifest] {
def newInstanceOfA(implicit m : Manifest[A]) : A =
m.erasure.newInstance.asInstanceOf[A]
}
你没有使用视图绑定! (您正在使用参数m
。)如果您想使用视图绑定,您可以这样做:
class SomeTraitOf[A : Manifest] {
def newInstanceOfA : A =
implicitly[Manifest[A]].erasure.newInstance.asInstanceOf[A]
}