简体   繁体   English

类型参数中的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]
}

(Not best naming, renamed them just to be brief.) (并不是最好的命名方式,只是为了简短起见,将其重命名。)
TreeNode1 defines a tree node with its children access, pointing their type S . TreeNode1定义一个具有其子级访问权限的树节点,指向其类型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定义了相同的对象,但其子对象与混合当前特征的类具有相同的类型(换句话说,具有统一子节点的树节点)。

In theory TreeNode2 is a particular case of TreeNode1 : 从理论上讲TreeNode2是一个特殊情况TreeNode1

trait TreeNode2 extends TreeNode1[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不会使用这种扩展来编译TreeNode2 ,因为不能以这种方式使用this.type ,尽管它在运行时的工作没有任何矛盾。

How can I get around this situation? 我如何解决这种情况? Or Scala do not offer such poorly used mechanism? 还是Scala不提供这种使用不良的机制?


The reason I need this construction is the following: 我需要这种构造的原因如下:

I have another trait that requires TreeNode1 to be mixed in. I also have some class that mixes TreeNode1 with quite another children type. 我还有另一个需要混合TreeNode1特性。我也有一些类将TreeNode1与另一TreeNode1类型混合在一起。 But I also have several classes which have the same type as they are: 但是我也有几个类具有相同的类型:

class SomeTreeNode extends TreeNode1[SomeTreeNode]

So it will look prettier if I use TreeNode2 for it: 因此,如果我使用TreeNode2 ,它将看起来更漂亮:

class SomeTreeNode extends TreeNode2

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. 但对于使用TreeNode2应的情况下TreeNode1 ,它实际上是,但斯卡拉不同意我的看法。

PS At least it is wondering as theoretical question about Scala, not for a wide practical use. PS:至少,这是关于Scala的理论性问题,而不是广泛的实际使用。

its children have the same type as the class the current trait is mixed 它的子代与当前特质混杂的班级具有相同的类型

No. This is a common misunderstanding. 不。这是一个常见的误解。 this.type is the singleton type of this ; this.type是的单类型this ; ie the type whose only two values are this and null . 只有两个值是thisnull All children of a TreeNode2 instance must be the same instance. TreeNode2实例的所有子代都必须是同一实例。

To answer the other part of your question, one option is to make S a type member instead of a type parameter: 要回答问题的另一部分,一个选择是使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]
}

(so-called Aux pattern), but whether this works for you depends on how they are used. (所谓的Aux模式),但是这对您是否有效取决于它们的使用方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM