类型参数中的 Scala trait `this.type`
Scala trait `this.type` in type parameter
看看这两个简单的特征:
trait TreeNode1[S] {
def subNodes: List[S]
}
trait TreeNode2 {
def subNodes: List[this.type]
}
(不是最好的命名,重命名只是为了简短。)
TreeNode1
定义了一个具有 children 访问权限的树节点,指向它们的类型 S
.
TreeNode2
定义相同,但它的 children 与当前特征混合的 class 具有相同的类型(换句话说,具有统一子节点的树节点)。
理论上TreeNode2
是TreeNode1
的特例:
trait TreeNode2 extends TreeNode1[this.type] {...}
但是Scala 不会用这样的扩展编译TreeNode2
,因为this.type
不能以这种方式使用,尽管没有任何不一致之处它在运行时工作。
我该如何解决这种情况?或者 Scala 不提供这种使用不当的机制?
我需要这个结构的原因如下:
我有另一个特征需要混合 TreeNode1
。我还有一些 class 将 TreeNode1
与另一种 children 类型混合。但我也有几个 classes,它们具有相同的类型:
class SomeTreeNode extends TreeNode1[SomeTreeNode]
所以用TreeNode2
会更漂亮:
class SomeTreeNode extends TreeNode2
执行相同的逻辑。但是使用 TreeNode2
应该是 TreeNode1
的情况,实际上是这样,但是 Scala 不同意我的看法。
P.S。至少它是关于 Scala 的理论问题,而不是广泛的实际用途。
its children have the same type as the class the current trait is mixed
没有。这是一个常见的误解。 this.type
是this
的单例类型;即 the type whose only two values are this
and null
。 TreeNode2
实例的所有子实例必须是同一个实例。
要回答问题的另一部分,一种选择是使 S
成为类型成员而不是类型参数:
trait TreeNode1 {
type S
def subNodes: List[S]
}
object TreeNode1 {
// use TreeNode1.Aux[S] where you had TreeNode1[S] originally
type Aux[T] = TreeNode1 { type S = T }
}
trait TreeNode2 {
type S = this.type // not really what you want
def subNodes: List[this.type]
}
(所谓的 Aux
模式),但这是否适合您取决于它们的使用方式。
看看这两个简单的特征:
trait TreeNode1[S] {
def subNodes: List[S]
}
trait TreeNode2 {
def subNodes: List[this.type]
}
(不是最好的命名,重命名只是为了简短。)
TreeNode1
定义了一个具有 children 访问权限的树节点,指向它们的类型 S
.
TreeNode2
定义相同,但它的 children 与当前特征混合的 class 具有相同的类型(换句话说,具有统一子节点的树节点)。
理论上TreeNode2
是TreeNode1
的特例:
trait TreeNode2 extends TreeNode1[this.type] {...}
但是Scala 不会用这样的扩展编译TreeNode2
,因为this.type
不能以这种方式使用,尽管没有任何不一致之处它在运行时工作。
我该如何解决这种情况?或者 Scala 不提供这种使用不当的机制?
我需要这个结构的原因如下:
我有另一个特征需要混合 TreeNode1
。我还有一些 class 将 TreeNode1
与另一种 children 类型混合。但我也有几个 classes,它们具有相同的类型:
class SomeTreeNode extends TreeNode1[SomeTreeNode]
所以用TreeNode2
会更漂亮:
class SomeTreeNode extends TreeNode2
执行相同的逻辑。但是使用 TreeNode2
应该是 TreeNode1
的情况,实际上是这样,但是 Scala 不同意我的看法。
P.S。至少它是关于 Scala 的理论问题,而不是广泛的实际用途。
its children have the same type as the class the current trait is mixed
没有。这是一个常见的误解。 this.type
是this
的单例类型;即 the type whose only two values are this
and null
。 TreeNode2
实例的所有子实例必须是同一个实例。
要回答问题的另一部分,一种选择是使 S
成为类型成员而不是类型参数:
trait TreeNode1 {
type S
def subNodes: List[S]
}
object TreeNode1 {
// use TreeNode1.Aux[S] where you had TreeNode1[S] originally
type Aux[T] = TreeNode1 { type S = T }
}
trait TreeNode2 {
type S = this.type // not really what you want
def subNodes: List[this.type]
}
(所谓的 Aux
模式),但这是否适合您取决于它们的使用方式。