Scala:具有易失性类型的val,用非易失性类型覆盖def

时间:2016-04-29 18:42:46

标签: scala

我一直试图理解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是易变类型?

2 个答案:

答案 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)

根据{{​​3}},

Foo2是易变的:第二种情况成立:Foo2 = T1 with T2,T1为抽象,T2为抽象类型成员。

当您使用volatile类型覆盖非易失性类型时,始终会出现此错误消息:Foo是非易失性的(因为没有1.-3。适用)。因此,为了使错误消失,有几种可能的方法:

  • 使HasFoo.foo的返回类型为volatile。这可以通过使用Foo with Foo而不仅仅是Foo来实现(根据3.6.1)。我认为,除此之外,Foo with FooFoo之间没有区别。所以下面的代码编译:

    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似乎没有帮助。