0

我正在查看“显式类型的自我引用”讨论。这个例子是这样开始的。

abstract class Graph {
  type Edge
  type Node <: NodeIntf
  abstract class NodeIntf {
    def connectWith(node: Node): Edge
  }
  def nodes: List[Node]
  def edges: List[Edge]
  def addNode: Node
}

该示例在self尝试声明Graph.

abstract class DirectedGraph extends Graph {
  ...
  class NodeImpl extends NodeIntf {
    def connectWith(node: Node): Edge = {
      val edge = newEdge(this, node)
      edges = edge :: edges
      edge
    }
  }
  protected def newEdge(from: Node, to: Node): Edge
  ...
}

问题是该函数newEdge期望 aNode作为它的第一个参数,但NodeImpl在内部调用它时得到 a connectWith

为什么这不是一个自己造成的问题?通过声明Node一个抽象类或一个特征开始而不是一个子类型来解决NodeIntf?如果这样做NodeImpl可以是一个子类,Node一切都会好起来的。

4

2 回答 2

0

我会说是和不是。

是的,如果您拥有所有代码,您可以更好地设计层次结构,以避免不必要的复杂性。

但是你假设你设计了Graph. 如果你没有呢?也许该类来自您无法更改的库或遗留代码,但您仍然希望使用它。

这个例子可能有点做作,但它旨在展示显式类型this如何解决某一类问题。

于 2013-11-10T19:50:13.503 回答
0

您展示的示例是关于家庭多态性的,它是一个研究案例

通过定义类型变量解决的问题Node

abstract class DirectedGraph extends Graph {
  ...
  type Node = NodeImp

  class NodeImpl extends NodeIntf {
  ...

花药解决方案是定义自我类型:

class NodeImpl extends NodeIntf {
    self: Node =>

你的解决方案是:

trait Edge

所有解决方案都是可以接受的。

我认为您参考了M.Odersky @ 2006的文章,它有点令人困惑,因为混合了许多概念:具有嵌入式多态性的类型变量、家族多态性和自键入。

恕我直言,这篇文章的想法是展示一组方差可能的解决方案。

于 2013-11-10T19:52:07.850 回答