在 Scala 中重写重复的类参数?
Scala 语言规范 2.8 版的第 4.6.2 节描述了重复参数并表示:
参数部分的最后一个值参数可以带有“*”后缀,例如(..., x:T*)。方法内此类重复参数的类型就是序列类型 scala.Seq[T]。
然而,这段代码:
abstract class A { def aSeq : Seq[A] }
class B(val aSeq : A*) extends A
class C extends B { override val aSeq :Seq[A] = Seq() }
编译时出现错误:
overriding value aSeq in class B of type A*; value aSeq has incompatible type
编译器似乎表明 A* 是与 Seq[A] 不同的类型。
在这种情况下调查 aSeq 的实际类表明它是 scala.collection.mutable.WrappedArray$ofRef 的实例,但即使以下代码也无法编译并显示相同的消息:
class C extends B { override val aSeq = new ofRef(Array[A]()) }
所以问题是,如何覆盖类中由重复参数定义的成员?
如果您想知道这是从哪里来的,这正是 scala.xml.Elem 用来重写 scala.xml.Node 中的 child 方法的方法。
Section 4.6.2 of the Scala Language Specification Version 2.8 describes repeated parameters and says:
The last value parameter of a parameter section may be suffixed by “*”, e.g. (..., x:T*). The type of such a repeated parameter inside the method is then the sequence type scala.Seq[T].
However, this code:
abstract class A { def aSeq : Seq[A] }
class B(val aSeq : A*) extends A
class C extends B { override val aSeq :Seq[A] = Seq() }
give an error when compiled:
overriding value aSeq in class B of type A*; value aSeq has incompatible type
The compiler seems to indicate that A* is a distinct type from Seq[A].
Investigating the actual class of aSeq in this case shows it to be an instance of scala.collection.mutable.WrappedArray$ofRef but even the following code fails to compile with the same message:
class C extends B { override val aSeq = new ofRef(Array[A]()) }
So the question is, how do I go about overriding a member defined by a repeated parameter on the class?
In case you're wondering where this is coming from, that is exacly what scala.xml.Elem does to override the child method in scala.xml.Node.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您的问题可以概括为:
方法有不同的类型。规范说(强调我的):
As
Int*
和Seq[Int]
不在方法内部,这句话不适用。有趣的是,下面的代码显示这些方法在擦除之前具有不同的类型,但在擦除之后具有相同的类型:
因此问题就变成了,为什么您的
B
类可以扩展您的A
抽象类。那里的规范可能存在不一致。我不知道...编辑:我重新阅读了规范,但我无法弄清楚是否有任何与重复参数和覆盖相关的内容。似乎没有任何关于重复参数的返回类型的信息,这是您从 val aSeq 访问器方法中获得的。
我认为马克的回答是一个完全有效的方法。如果您无法遵循它,您可以使用以下解决方法:
例如:
然后:
Your issue can be summarized as:
The methods have different types. The spec says (emphasis mine):
As
Int*
andSeq[Int]
aren't inside the method, this particular sentence does not apply.Interestingly, this following code shows that the methods have different types before erasure but the same after:
So the question then becomes, why your
B
class can extend yourA
abstract class. There may be an inconsistency in the spec there. I don't know...Edit: I re-read the spec and I can't figure out if there is anything related to repeated parameters and overriding. There does not seem to be anything about return type of repeated parameters, which is what you get for the
val aSeq
accessor method.I think Mark's answer is a perfectly valid approach. In case you can't follow it, you can use the following workaround:
So for instance:
Then:
xml.Elem
的copy方法是这样使用的所以你可以重写
B
构造函数中的值或者将其声明为类
C
的参数code>虽然我不确定它是否回答了你的问题!
The copy method of
xml.Elem
uses it like thisSo you can override the value in the
B
constructorOr declare it as a parameter of the class
C
Though I am not sure it answers your question!
该规范从来不允许重复类型以这种方式泄漏。编译器于 2011 年 7 月进行了更改以强制执行此操作。
有关更多背景信息,请查看票证中的评论:
https://issues.scala-lang .org/browse/SI-4176
The spec never allowed for repeated types to leak out in this way. The compiler was changed in July 2011 to enforce this.
For more background, check out the comments in the ticket:
https://issues.scala-lang.org/browse/SI-4176