繁体   English   中英

Scala使用var覆盖非抽象def

[英]Scala overriding a non-abstract def with a var

在Scala我可以这样做:

trait SomeTrait {
  protected def foo: String
}

class Wibble extends SomeTrait {
  protected var foo = "Hello"
}

但我不能做同样的事情,我提供foo的默认定义

trait SomeTrait {
  protected def foo: String = "World"
}

class Wibble extends SomeTrait {
  protected var foo = "Hello" //complains about lack of override modifier

  override protected var foo = "Hello" //complains "method foo_ overrides nothing"
}

为什么我不能这样做?

编辑:在scala-users邮件列表上进行对话后,我在trac中提出了这个问题

在Scala中,当您编写var foo ,Scala编译器会自动为它生成一个setter(称为foo_= )和一个getter(称为foo ),并将该字段设置为private(如果您反编译,则会将其视为私有)有javap '公共'Scala字段的类)。 这就是'方法foo_ =无所事事'错误意味着什么。 在你的特质中,你还没有定义一个foo_=方法,对于公共字段设置器和getter 总是成对出现。

如果您没有在特征中提供默认值(即抽象方法),则不需要override关键字。 因此,在您的第一个示例中,getter重写了抽象方法和setter ......它就在那里。 编译器没有抱怨。 但是当您在trait中提供方法的实际实现时,您需要在override时专门编写override关键字。 在编写protected var foo ,您没有为getter指定override关键字,并且在写入override protected var foo ,您还向编译器指示要覆盖方法foo_= ,但是trait没有这样的方法。

另外,从逻辑上讲,你不能真正用var覆盖def (考虑严格的覆盖视图,如前一段所述)。 def在逻辑上是一个函数(你给它一些输入,它产生一个输出)。 var类似于无参数函数,但也支持将其值设置为其他函数,这是函数不支持的操作。 相反,如果您将其更改为val ,则可以。 它就像一个总是产生相同(缓存)结果的函数。

如果你想要与var有类似的行为,你可以做这样的事情(通过明确的setter和getter):

class Wibble extends SomeTrait {
  private var bar = "Hello"
  override protected def foo = bar
  protected def foo_=(v: String) { bar = v}
}

现在你可以用var :)做任何事情。

val x = new Wibble
println(x.foo) // yields "Hello"
x.foo = "Hello again"
println(x.foo) // yields "Hello again"

暂无
暂无

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

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