首页 文章

如何在Scala中使用参数化特征的反射?

提问于
浏览
4

对于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不能为参数特征提供清单,实现特征的类应该,但我没有得到它 .

1 回答

  • 4

    About covariance

    由于 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!
    

    About View Bounds

    从下面的评论中,我猜你也在询问“视图边界”,这只是一种声明隐式参数的简洁方法 . 你的声明

    class SomeTraitOf[A : Manifest] { ...
    

    基本上翻译成

    class SomeTraitOf[A]()(implicit m0: Manifest[A]) { ....
    

    特征不能具有视图边界,因为它们不能获取任何(值)参数 . 但这不是一个真正的问题,因为在你的例子中

    class SomeTraitOf[A : Manifest] {
      def newInstanceOfA(implicit m : Manifest[A]) : A =
         m.erasure.newInstance.asInstanceOf[A] 
    }
    

    你're not using the view bound! (You'重新使用参数 m . )如果你想使用视图绑定,你可以这样做:

    class SomeTraitOf[A : Manifest] {
      def newInstanceOfA : A =
         implicitly[Manifest[A]].erasure.newInstance.asInstanceOf[A] 
    }
    

相关问题