Самотипы Scala и this.type в выпуске коллекций

Я пытаюсь осмыслить абстрактные и явные типы self в scala. Давайте рассмотрим этот пример: Я хочу создать основу для расширяемого дерева так просто:

trait Tree {
  def children: Iterable[Tree]
  def descendants: Iterable[Tree] = { val dv = children.view; dv ++ (dv.flatMap { _.children }) }
}

Однако я хочу иметь возможность расширять узлы дерева с помощью некоторых методов и использовать такие методы, как: tree.children foreach {_.newMethod () }

Для этого я пробовал:

A. this.type: FAIL

trait Tree {
    def children: Iterable[this.type] 
    def descendants: Iterable[this.type] = {
      val dv = children.view
      // FAIL: type mismatch;  found   :  scala.collection.IterableView[com.abovobo.data.Tree,Iterable[_]]  required: Iterable[Tree.this.type] 
      // dv ++ (dv.flatMap { _.children })
      // OK: 
      dv.++[this.type, Iterable[this.type]](dv.flatMap[this.type, Iterable[this.type]]{ _.children })
    }
}

Рабочий вариант довольно корявый.

Б. Абстрактные типы: FAIL

trait Tree {
    type Node <: Tree

    def children: Iterable[Node]  
    def descendants: Iterable[Node] = {
        val dv = children.view
        // FAIL: type mismatch;  found   : scala.collection.IterableView[com.abovobo.data.Tree#Node,Iterable[_]]  required: Iterable[Tree.this.Node] 
        dv ++ (dv.flatMap { _.children })
    }
}

Не работает вообще из-за несоответствия типов для конкретного пути, как я понял.

С. Тип params (generics): OK

trait Tree[+Node <: Tree[Node]] {

    def children: Iterable[Node]

    def descendants: Iterable[Node] = {
       val dv = children.view
       dv ++ (dv.flatMap { _.children })
    }
}

Работает нормально, но не очень удобно поддерживать в производных классах.

Есть идеи, как заставить работать первые два варианта без тонны кода?

Кроме того, с this.type у меня возникли проблемы с реализацией.

trait BiDTree extends Tree {
    def parent: Option[this.type]
}

// how to accept this param? Option[TreeImpl] doesn't work. 
class TreeImpl(val parent: Option[???]) extends BiDTree {
  // ...
}

Спасибо!

9
задан tuxSlayer 8 February 2012 в 07:59
поделиться