工作通过 these posts让我认为我了解自我类型,至少在某种程度上。
所以我创建了一个按预期失败的例子:
scala> trait A { val v = "a" }
defined trait A
scala> trait B { this :A => ; var v = "" ; this.v = "b" }
<console>:6: error: reassignment to val
trait B { this :A => ; var v = "" ; this.v = "b" }
^
自我类型的“这个”阴影 B 的“这个”——看起来很奇怪,但有道理。
那么,给自我类型一个不同的名字似乎是明智的。我这样做了,而且相当惊讶:
scala> trait C { a :A => ; var v = "" ; this.v = "c" }
<console>:6: error: reassignment to val
trait C { a :A => ; var v = "" ; this.v = "c" }
^
还是有阴影???
更改“本地”变量的名称让事情编译,这是有道理的:
scala> trait D { a :A => ; var w = "" ; this.w = a.v }
defined trait D
(并且可以选择使用自类型名称来阐明要使用的“v”。)
好的。这意味着以下应该失败?
scala> trait E { this :A => ; var w = "" ; this.w = this.v }
defined trait E
嗯?这是哪个? :-(
那么......命名自我类型有什么意义吗?不管怎样,“这个”似乎最终都被遮蔽了。
或者这是范围规则的边缘情况,其中自我类型的“this”优先于特征的“this”——并且应该避免对相关特征中的事物使用相同的名称?
最佳答案
您的问题不是 self 类型的名称(在您的所有示例中, this
和备用 self-type 名称都指代完全相同的事物并且具有相同的类型,即“B
和 A
的最大下限”[§5.1] , Scala Language Spec]) 但您尝试再次定义具有相同名称的字段而不显式覆盖它。
看一个更简单的例子:
trait A { val v = "a" }
trait B { this: A =>
var v = "b"
}
new A with B {} // does not compile
<console>:9: error: overriding value v in trait A$class of type java.lang.String;
variable v in trait B$class of type java.lang.String needs `override' modifier
new A with B {}
因此,即使您在定义
B
时不会出错,但无论如何您根本无法使用它。这会工作
trait A { val v = "a" }
trait B { this:A => override val v = "b" }
new A with B {}
在这里,您在
A
中明确覆盖了 v
的 B
。 (注意 new B with A {}
会失败,因为 B
需要放在最后。)此外,它必须是 val
因为在大多数情况下你不能真正覆盖 var
并且你不能使用 var
覆盖其他东西通常,在这些简单的情况下,您不应该关心自类型的名称。只要您不在
B
内创建另一个特征或类, this
和您称之为 self 类型变量的任何东西都将指向同一事物。不会有阴影。如果您在 B
中有一个新特征,并且您需要在该特征中引用 B
的实例,则您的 self 类型需要另一个名称。考虑这个
trait B { this =>
val v = "b"
trait C {
val v = "c"
println(this.v)
}
new C {}
}
new B {}
// prints c
与这个:
trait B { self =>
val v = "b"
trait C {
val v = "c"
println(this.v) // prints c
println(self.v) // prints b
}
new C {}
}
new B {}
(在没有任何进一步类型注释的情况下,您可以省略本示例中的所有
this
。)
关于scala - 名为 Scala 自类型仍然阴影 "this"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4741724/