在 Scala 中覆盖重复的类参数? [英] Overriding a repeated class parameter in Scala?

查看:44
本文介绍了在 Scala 中覆盖重复的类参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Scala 语言规范版本 2.8 的第 4.6.2 节描述了重复参数并说:

Section 4.6.2 of the Scala Language Specification Version 2.8 describes repeated parameters and says:

参数部分的最后一个值参数可以带有*"后缀,例如(..., x:T*).方法中这样一个重复参数的类型就是序列类型 scala.Seq[T].

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

但是,这段代码:

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] 不同的类型.

The compiler seems to indicate that A* is a distinct type from Seq[A].

在这种情况下调查 aSeq 的实际类表明它是 scala.collection.mutable.WrappedArray$ofRef 的一个实例,但即使是以下代码也无法编译并显示相同的消息:>

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?

如果您想知道这是从哪里来的,这正是 scala.xml.Elem 为覆盖 scala.xml.Node 中的 child 方法所做的.

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.

推荐答案

您的问题可以概括为:

scala> class A { def aSeq(i: Int*) = 1 }
defined class A

scala> class B extends A { override def aSeq(i: Seq[Int]) = 2 }
<console>:6: error: method aSeq overrides nothing
       class B extends A { override def aSeq(i: Seq[Int]) = 2 }

方法有不同的类型.规范说(强调我的):

The methods have different types. The spec says (emphasis mine):

这种重复参数的类型内部就是序列类型scala.Seq[T]

The type of such a repeated parameter inside the method is then the sequence type scala.Seq[T]

由于 Int*Seq[Int] 不在方法内部,所以这句话不适用.

As Int* and Seq[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:

scala> class G { def aSeq(i:Int*) = 1; def aSeq(i:Seq[Int]) = 2 }
<console>:5: error: double definition:
method aSeq:(i: Seq[Int])Int and
method aSeq:(i: Int*)Int at line 5
have same type after erasure: (i: Seq)Int
       class G { def aSeq(i:Int*) = 1; def aSeq(i:Seq[Int]) = 2 }

那么问题就变成了,为什么您的 B 类可以扩展您的 A 抽象类.那里的规范可能不一致.我不知道...

So the question then becomes, why your B class can extend your A abstract class. There may be an inconsistency in the spec there. I don't know...

我重新阅读了规范,但我不知道是否有任何与重复参数和覆盖相关的内容.似乎没有关于重复参数的返回类型的任何内容,这是您从 val aSeq 访问器方法中得到的.

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:

class C extends B {
  private def aSeqHelper(a: A*) = a
  override val aSeq = aSeqHelper(Seq[A](): _*)
}

例如:

import scala.xml._
class ElemX extends Elem("pref", "label", <xml a="b"/>.attributes, TopScope) {
  private def childHelper(c: Node*) = c
  override val child = childHelper(<foo/><bar/>: _*) }

那么:

scala> new ElemX
res4: ElemX = <pref:label a="b"><foo></foo><bar></bar></pref:label>

这篇关于在 Scala 中覆盖重复的类参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆