我一直试图理解Scala不允许以下内容:
trait WhatsWrong {
type Foo
trait HasFoo {
def foo: Foo
}
type Foo2 = Foo with HasFoo2
trait HasFoo2 extends HasFoo {
override val foo: Foo2 // <-- error here
// override def foo: Foo2 // <-- this works though
}
}
错误:在类型=&gt;的特征HasFoo中覆盖方法foo WhatsWrong.this.Foo; value foo具有volatile类型;不能覆盖非易失性类型的成员
override val foo: WhatsWrong.this.Foo2
为什么Foo2
是易变类型?
答案 0 :(得分:1)
我之前遇到过这种情况,它与抽象(尚未定义)的访问器(如val和def)的动态特性有关。在这种情况下,只需使用def而不是val,它就会编译。
trait HasFoo2 extends HasFoo {
override def foo: Foo2 // <-- error here
// override def foo: Foo2 // <-- this works though
}
答案 1 :(得分:1)
Foo2
是易变的:第二种情况成立:Foo2 = T1 with T2
,T1为抽象,T2为抽象类型成员。
当您使用volatile类型覆盖非易失性类型时,始终会出现此错误消息:Foo
是非易失性的(因为没有1.-3。适用)。因此,为了使错误消失,有几种可能的方法:
使HasFoo.foo
的返回类型为volatile。这可以通过使用Foo with Foo
而不仅仅是Foo
来实现(根据3.6.1)。我认为,除此之外,Foo with Foo
和Foo
之间没有区别。所以下面的代码编译:
trait WhatsWrong {
type Foo
trait HasFoo {
def foo: Foo with Foo
}
type Foo2 = Foo with HasFoo2
trait HasFoo2 extends HasFoo {
override val foo: Foo2 // <-- hey, now this works :)
// override def foo: Foo2 // <-- this works, too
}
}
嗯,我认为@uncheckedStable会有一些可能的东西(见http://www.scala-lang.org/files/archive/spec/2.11/03-types.html#volatile-types),但似乎并非如此:用@ annotations.unchecked注释volatile值。 uncheckedStable似乎没有帮助。