为什么我需要在给定的例子中明确使用self-type?

时间:2013-10-08 19:09:22

标签: scala inheritance types self-type upperbound

在阅读并尝试从this获取Scala中可扩展组件背后的所有概念时,我仍然无法完全理解为什么这个示例应该具有自我类型:

abstract class Graph {
  type Node <: NodeLike
    trait NodeLike {    // without self: Node => won't compile
      def connectWith(n: Node) =
    new Edge(this, n)
    }           
    class Edge(from: Node, to: Node)
}

抽象类型NodeNodeLike的子类型,thisNodeLike类型的对象,它根据给定的上限约束。任何详细的解释将不胜感激。

2 个答案:

答案 0 :(得分:3)

由于绑定Node <: NodeLike,它正确地失败了。当您执行new Edge(this,n)时,您只需将参数类型作为NodeLike, Node传递给Edge。但是您的Edge期望'Node,Node`:

class Edge(from: Node, to: Node)

即。您正尝试将NodeLike传递给Node(NodeLike是超级节点类型)。这就像将动物传递给期待狗的功能一样(问题是,如果它被允许,那么你可以将包括猫在内的任何动物传递给期待狗的动物)

解决方法是:

abstract class Graph {
    type Node <: NodeLike
    trait NodeLike { // without self: Node => won't compile
      def connectWith(n: Node) =
        new Edge(this, n)
    }
    class Edge(from: NodeLike, to: Node)
  }

或者另一种方式就是你所提到的,你明确保证你传递的参数是Node类型而不是NodeLike。

答案 1 :(得分:0)

在定义中

def connectWith(n: Node) = new Edge(this, n)

this的类型为NodeLike,但Edge的构造函数要求from的类型为Node,这是NodeLike的子类型}。您需要自我类型注释,以确保this具有所需的Node类型。