类型参数中的Scala特征`this.type` [英] Scala trait `this.type` in type parameter
问题描述
看看这两个简单的特征:
Have a look at these two simple traits:
trait TreeNode1[S] {
def subNodes: List[S]
}
trait TreeNode2 {
def subNodes: List[this.type]
}
(不是最好的命名,重命名只是为了简短.)TreeNode1
定义了一个树节点及其子节点访问,指向它们的类型 S
.TreeNode2
定义相同,但其子节点具有与当前特征混合的类相同的类型(换句话说,具有统一子节点的树节点).
(Not best naming, renamed them just to be brief.)
TreeNode1
defines a tree node with its children access, pointing their type S
.
TreeNode2
defines the same, but its children have the same type as the class the current trait is mixed in (another words, tree node with uniform subnodes).
理论上TreeNode2
是TreeNode1
的一个特例:
In theory TreeNode2
is a particular case of TreeNode1
:
trait TreeNode2 extends TreeNode1[this.type] {...}
但是Scala不会用这样的扩展编译TreeNode2
,因为this.type
不能这样使用,虽然有它在运行时的工作没有任何不一致.
But Scala will not compile TreeNode2
with such an extension, because this.type
can not be used in such way, although there are no any inconsistencies with its working in runtime.
我该如何解决这种情况?或者 Scala 没有提供这种不好用的机制?
How can I get around this situation? Or Scala do not offer such poorly used mechanism?
我需要这种结构的原因如下:
我有另一个特征需要混合 TreeNode1
.我还有一些类将 TreeNode1
与另一种子类型混合.但我也有几个类,它们的类型与它们相同:
I have another trait that requires TreeNode1
to be mixed in. I also have some class that mixes TreeNode1
with quite another children type. But I also have several classes which have the same type as they are:
class SomeTreeNode extends TreeNode1[SomeTreeNode]
所以如果我使用 TreeNode2
它会看起来更漂亮:
So it will look prettier if I use TreeNode2
for it:
class SomeTreeNode extends TreeNode2
实现相同的逻辑.但是对于使用 TreeNode2
应该是 TreeNode1
的情况,它实际上是,但 Scala 不同意我的看法.
Implementing the same logic. But for using TreeNode2
should be a case of TreeNode1
, which it actually is, but Scala doesn't agree with me.
附言至少它是关于 Scala 的理论问题,而不是广泛的实际用途.
P.S. At least it is wondering as theoretical question about Scala, not for a wide practical use.
推荐答案
它的子类与当前 trait 混合的类具有相同的类型
its children have the same type as the class the current trait is mixed
没有.这是一个普遍的误解.this.type
是this
的单例类型;即 只有两个值是this
和 null
.TreeNode2
实例的所有子节点必须是同一个实例.
No. This is a common misunderstanding. this.type
is the singleton type of this
; i.e. the type whose only two values are this
and null
. All children of a TreeNode2
instance must be the same instance.
要回答问题的另一部分,一种选择是使 S
成为类型成员而不是类型参数:
To answer the other part of your question, one option is to make S
a type member instead of a type parameter:
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
模式),但这是否适合您取决于它们的使用方式.
(so-called Aux
pattern), but whether this works for you depends on how they are used.
这篇关于类型参数中的Scala特征`this.type`的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!