Почему мне нужно явно использовать self-type в данном примере?

Читая и пытаясь извлечь из этого все концепции, лежащие в основе масштабируемых компонентов в Scala, я все еще не могу полностью понять, почему этот пример должен иметь тип self:

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)
}

абстрактный тип Node это подтип NodeLike а также this является объектом типа NodeLike который подходит в соответствии с данным верхним ограничением. Любое подробное объяснение будет оценено.

2 ответа

Ну, это справедливо терпит неудачу из-за связанной Node <: NodeLike, Когда вы делаете new Edge(this,n)вы просто передаете типы аргументов как NodeLike, Node к краю. Но твой Edge ожидает 'Node,Node`:

class Edge(from: Node, to: Node)

т.е. ты пытаешься пройти NodeLike в Node (NodeLike - супер тип Node). Это похоже на передачу животного функции, которая ожидает собаку (проблема в том, что если это разрешено, то вы можете передать любое животное, включая кошку, одной ожидающей собаке)

Обходной путь будет:

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.

В определении

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

this имеет тип NodeLikeОднако конструктор для Edge требует, чтобы from имеет тип Node, который является подтипом NodeLike, Вам нужно аннотации типа себя, чтобы убедиться, что this имеет требуемый тип Node,

Другие вопросы по тегам