Scala: основной тип коллекции - PullRequest
2 голосов
/ 20 января 2011
class AbstractNode

class Node extends AbstractNode {
  def update() {
    // update something here
  }
}

class AbstractGraph {
  val allNodes = ArrayBuffer[AbstractNode]()
}

class Graph extends AbstractGraph {
  override val allNodes = ArrayBuffer[Node]()
  def updateAll() {
    allNodes.foreach(_.update())
  }
}

Выше выдает ошибку:

overriding value allNodes in class AbstractGraph of type scala.collection.mutable.ArrayBuffer[AbstractNode];
value allNodes has incompatible type
override val allNodes = ArrayBuffer[Node]()
             ^

Как правильно добавить метод update в Node? Связано ли это с Путешествие по Скала: Явные ссылки на личность ?

Ответы [ 3 ]

7 голосов
/ 20 января 2011

Поскольку ArrayBuffer [Node] не является подтипом ArrayBuffer [AbstraceNode]. Это как-то связано с Variances . В scala A подтип B не означает, что S [A] является подтипом S [B]. Это может привести к подтипу S [A] S [B] или к подтипу S [B] S [A] или к ничему.

Например:

scala> class A
defined class A

scala> class B extends A
defined class B

scala> class S1[+T]
defined class S1

scala> val s11: S1[A] = null.asInstanceOf[S1[B]]
s11: S1[A] = null

scala> val s12: S1[B] = null.asInstanceOf[S1[A]]
<console>:8: error: type mismatch;
 found   : S1[A]
 required: S1[B]
       val s12: S1[B] = null.asInstanceOf[S1[A]]
                                         ^

scala> class S2[-T]
defined class S2

scala> val s21: S2[A] = null.asInstanceOf[S2[B]]
<console>:8: error: type mismatch;
 found   : S2[B]
 required: S2[A]
       val s21: S2[A] = null.asInstanceOf[S2[B]]
                                         ^

scala> val s22: S2[B] = null.asInstanceOf[S2[A]]
s22: S2[B] = null

scala> class S3[T]
defined class S3

scala> val s31: S3[A] = null.asInstanceOf[S3[B]]
<console>:8: error: type mismatch;
 found   : S3[B]
 required: S3[A]
Note: B <: A, but class S3 is invariant in type T.
You may wish to define T as +T instead. (SLS 4.5)
       val s31: S3[A] = null.asInstanceOf[S3[B]]
                                         ^

scala> val s32: S3[B] = null.asInstanceOf[S3[A]]
<console>:8: error: type mismatch;
 found   : S3[A]
 required: S3[B]
Note: A >: B, but class S3 is invariant in type T.
You may wish to define T as -T instead. (SLS 4.5)
       val s32: S3[B] = null.asInstanceOf[S3[A]]

Edit:

class AbstractNode

class Node extends AbstractNode {
  def update() {
    // update something here
  }
}

class AbstractGraph[T <: AbstractNode] {
  val allNodes = ArrayBuffer[T]()
}

class Graph extends AbstractGraph[Node] {
  def updateAll() {
    allNodes.foreach(_.update())
  }
}
1 голос
/ 20 января 2011

Я довольно новичок в Scala, но я думаю, что вы хотите здесь абстрактные типы , которые используются в примерах кода на странице, на которую вы ссылаетесь. Я думаю, что причина того, что вы получаете эту ошибку, заключается в том, что вы пытаетесь сузить тип allNodes от AbstractNode до Node. Это означает, что ваша конкретная реализация несовместима с типом AbstractGraph, и вы не можете использовать экземпляр Graph везде, где вы можете использовать AbstractGraph.

Если вы хотите сделать это, то вы хотите использовать абстрактные типы. Абстрактный тип говорит, что будет существовать некоторый тип, и конкретная реализация должна создать его экземпляр. В приведенном ниже коде AbstractGraph говорит, что конкретная реализация должна указывать тип node, который является подтипом AbstractNode, а Graph указывает, что это тип Node.

import scala.collection.mutable.ArrayBuffer

class AbstractNode

class Node extends AbstractNode {
  def update() {
    // update something here
  }
}

class AbstractGraph {
  type node <: AbstractNode
  val allNodes = new ArrayBuffer[node]()
}

class Graph extends AbstractGraph {
  override type node = Node
  def updateAll() {
    allNodes.foreach(_.update())
  }
}
0 голосов
/ 21 января 2011

Старайтесь использовать неизменные коллекции вокруг.Это будет намного проще, потому что неизменяемые коллекции могут быть ковариантными.

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