关于self =>在斯卡拉

时间:2013-11-10 19:20:11

标签: scala

我正在查看"明确输入的自我引用" discussion。这个例子就是这样开始的。

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期望Node作为其第一个参数,但在NodeImpl内的调用中获得connectWith

为什么这不是一个自我造成的问题?通过声明Node 抽象类特征来开始而不是NodeIntf的子类型,是不是很容易解决?如果已经完成NodeImpl可能是Node的子类,一切都会好的。

2 个答案:

答案 0 :(得分:0)

我会说是和不。

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

但是你假设你设计了Graph。如果你没有怎么办?也许这个课程来自你无法改变的图书馆或遗留代码,但你仍然希望利用它。

这个例子可能有点人为,但它是为了演示如何明确地键入this来解决某类问题。

答案 1 :(得分:0)

您展示的关于家庭多态性的示例,它是学习案例

定义类型变量Node解决了问题。

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

  class NodeImpl extends NodeIntf {
  ...

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

class NodeImpl extends NodeIntf {
    self: Node =>

你的解决方案是:

trait Edge

所有解决方案均可接受。

我认为你引用文章M.Odersky @ 2006并且它有点令人困惑,因为混合了很多概念:类型变量具有嵌入式多态性,家族多态性和自我键入。

Imho想要这篇文章来展示一组方差可能的解决方案。