如何在Scala中使用参数化特征的反射?(How to use reflection on parameterized trait in Scala?)

编程入门 行业动态 更新时间:2024-10-26 13:21:14
如何在Scala中使用参数化特征的反射?(How to use reflection on parameterized trait in Scala?)

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

The access on Manifest seems to be tricky from a trait in scala.

How could this code compile in scala ?

trait SomeTraitOf[+A] { def newInstanceOfA : A = /* necessary code to make it work */ }

(Related, it works fine as a parametized class :

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

but not with a covariant type parameter (+A))

Edit : The real stuff

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] } }

Since traits cannot provide manifest for the parametized trait, the class implementing the trait should, but I am not getting it.

最满意答案

关于协方差

由于Manifest[A]在参数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]) { ....

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

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] }

About covariance:

Since Manifest[A] is invariant in the parameter A, you can't do what you want directly. The usual strategy is to weaken the return type,

trait SomeTraitOf[+A] { def newInstance[B >: A](implicit m: Manifest[B]): B = { m.erasure.newInstance.asInstanceOf[B] } }

You can use the trait as follows,

class Parent class Child extends Parent val childBuilder = new SomeTraitOf[Child] {} val parentBuilder: SomeTraitOf[Parent] = childBuilder parentBuilder.newInstance // returns a Parent!

About View Bounds:

From your comment below, I guess you're also asking about "view bounds", which are just a concise way of declaring an implicit parameter. Your declaration

class SomeTraitOf[A : Manifest] { ...

basically translates to

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

Traits can't have view bounds because they can't take any (value) parameters. But that's not really a problem here, because in your example

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

you're not using the view bound! (You're using the parameter m instead.) If you wanted to use the view bound, you could do it this way:

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

更多推荐

本文发布于:2023-08-04 13:57:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1415916.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:反射   特征   参数   如何在   Scala

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!