Scala自我类型和collection.issue中的this.type [英] Scala self type and this.type in collections issue

查看:121
本文介绍了Scala自我类型和collection.issue中的this.type的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试把自己的头放在scala中的抽象和显式自身类型上. 让我们考虑这个例子: 我想像这样简单地为可扩展树创建基础:

I'm trying to wrap my head around abstract and explicit self types in scala. Lets consider this example: I want to create a base for extensible tree as simple as this:

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

但是,我希望能够使用某些方法扩展树节点并使用以下方法,例如:tree.children foreach { _.newMethod() }

However, I want to be able to extend tree nodes with some methods and use these methods like: tree.children foreach { _.newMethod() }

为此,我已经尝试过:

A.此类型:失败

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

工作变体非常笨拙.

B.抽象类型:失败

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

由于我所理解的路径特定类型不匹配,因此根本无法工作.

Doesn't work at all due to path specific type mismatch as I understood.

C.键入params(泛型):确定

C. Type params (generics): OK

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

    def children: Iterable[Node]

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

可以,但是在派生类中维护不太好.

Works OK, but not so good to maintain in derived classes.

有什么想法可以使前两个变体在没有大量代码的情况下工作?

Any ideas how to make first two variants working without a tons of code?

此外,使用this.type我在实现方面遇到了问题.

Also, with this.type I've run into problems with implementation.

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 {
  // ...
}

谢谢!

推荐答案

最后,我已经解决了本次讨论中提出的建议

At the end I've settled with what was proposed in this discussion http://www.scala-lang.org/node/6649:

trait Tree[+Node <: Tree[Node]] {
    this: Node =>

    def children: Iterable[Node]

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

即变体(C),但具有明确的自我类型.这提供了在其他方法(例如方法find(path: String): Option[Node])中使用this的机会.

I.e. variant (C) but with explicit self type. This gives a chance to use this in other methods (say, method find(path: String): Option[Node]).

这篇关于Scala自我类型和collection.issue中的this.type的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆