如何在Spark的TreeNode中解释TreeNode类型限制和自我类型?

exp*_*ter 5 scala treenode self-type apache-spark-sql

从Spark SQL 中TreeNode的定义:

abstract class TreeNode[BaseType <: TreeNode[BaseType]] extends Product {
  self: BaseType =>
  ...
}
Run Code Online (Sandbox Code Playgroud)

这是什么说的亚型TreeNode和BaseType?什么是可以接受的?

Mar*_*nne 5

自我类型

首先,看看所谓的self-types:Andrew Rollins 的博客对Self Type Annotations vs. Inheritance 做了很好的介绍。

基本上,一个 self 类型,写成

trait Foo { self: SomeType =>
  ...
}
Run Code Online (Sandbox Code Playgroud)

说,特征Foo只能混合在一个也实现SomeType. 继承和自类型之间的区别也很好地解释了here。

通常,自我类型用于依赖注入,例如在Cake Pattern 中。

类型限制

鉴于类型定义:

class TreeNode[BaseType <: TreeNode[BaseType]] {
  self: BaseType with Product =>
  // ...
}
Run Code Online (Sandbox Code Playgroud)
  1. 定义TreeNode[BaseType <: TreeNode[BaseType]]说: TreeNode 的类型化使得类型参数BaseType至少(在子类化的意义上)也是一个TreeNode[BaseType]. 粗略地说,这意味着:类型参数也必须是 aTreeNode本身。

  2. 这里的 self 类型要求,TreeNode只有当它也提供Product.

具体例子

示例 1

class IntTreeNode extends TreeNode[Int] {}
Run Code Online (Sandbox Code Playgroud)

由于以下原因无法编译:

  1. 类型参数Int不符合类TreeNode的类型参数边界,即[BaseType <: TreeNode[BaseType]]
  2. 由于自身类型限制导致的非法继承。

示例 2

class IntTreeNode2 extends TreeNode[IntTreeNode2]
Run Code Online (Sandbox Code Playgroud)

由于以下原因无法编译:

  1. 由于自身类型限制导致的非法继承。

示例 3

class TupleTreeNode extends TreeNode[TupleTreeNode] with Product1[Int] {
  // implementation just to be a `Product1` 
  override def _1: Int = ???
  override def canEqual(that: Any): Boolean = ???
}
Run Code Online (Sandbox Code Playgroud)

确实编译由于:

  1. 类型约束onBaseType和self type都得到满足。所以,这就是原始定义所要求的。

评论

在docs.scala-lang.org上也给出了一个类似于你的(催化剂)的例子