Переопределить повторный параметр класса в Scala? - PullRequest
7 голосов
/ 01 апреля 2011

Раздел 4.6.2 спецификации языка Scala версии 2.8 описывает повторяющиеся параметры и говорит:

Последний параметр значения раздела параметров может содержать суффикс «*», например (...х: Т *).Тип такого повторного параметра внутри метода является типом последовательности 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 делает дляпереопределить метод child в scala.xml.Node.

Ответы [ 3 ]

5 голосов
/ 01 апреля 2011

Ваш вопрос можно суммировать как:

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 }

Методы имеют разные типы. В спецификации сказано (выделено мое):

Тип такого повторяющегося параметра внутри . Метод имеет тип последовательности scala.Seq [T]

Поскольку Int* и Seq[Int] не находятся внутри метода, это конкретное предложение неприменимо.

Интересно, что следующий код показывает, что методы имеют различные типы до стирания, но одинаковые после:

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 абстрактный класс. Там может быть несоответствие в спецификации там. Я не знаю ...

Редактировать: я перечитал спецификацию и не могу понять, есть ли что-нибудь, связанное с повторяющимися параметрами и переопределением. Похоже, что-то не относится к типу возвращаемых повторяющихся параметров, что вы получаете для метода доступа val aSeq.

Я думаю, что ответ Марка - совершенно правильный подход. Если вы не можете следовать этому, вы можете использовать следующий обходной путь:

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>
4 голосов
/ 01 апреля 2011

Метод копирования xml.Elem использует его следующим образом

def copy(
  prefix: String = this.prefix,
  label: String = this.label,
  attributes: MetaData = this.attributes,
  scope: NamespaceBinding = this.scope,
  child: Seq[Node] = this.child.toSeq
): Elem = Elem(prefix, label, attributes, scope, child: _*)

Таким образом, вы можете переопределить значение в конструкторе B

class C extends B(aSeq = Seq(): _*)

Или объявить его как параметр класса C

class C(seq: Seq[A]) extends B(aSeq = seq: _*)

Хотя я не уверен, что он отвечает на ваш вопрос!

3 голосов
/ 20 января 2012

В спецификации никогда не допускается утечка повторяющихся типов таким образом.Для обеспечения этого компилятор был изменен в июле 2011 года.

Для получения дополнительной информации просмотрите комментарии в заявке:

https://issues.scala -lang.org / browse / SI-4176

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...