在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邮件列表上进行对话后,我有raised this in trac
答案 0 :(得分:21)
在Scala中,当您编写var foo
时,Scala编译器会自动为其生成一个setter(称为foo_=
)和一个getter(称为foo
),并将该字段设置为private(如果您使用javap
反编译具有'公共'Scala字段的类,您将看作私有。这就是'方法foo_ =无所事事'错误意味着什么。在您的特质中,您没有定义foo_=
方法,而公共字段设置器和getter 总是成对出现。
如果您没有在特征中提供默认值(即抽象方法),则不需要override
关键字。因此,在您的第一个示例中,getter重写了抽象方法和setter ......它就在那里。编译器没有抱怨。但是当您在特征中提供方法的实际实现时,您需要在覆盖时专门编写override
关键字。在编写protected var foo
时,您没有为getter指定override
关键字,在编写override protected var foo
时,您还向编译器表明要覆盖方法foo_=
,但特质没有这样的方法。
另外,从逻辑上讲,你不能真正用def
覆盖var
(考虑严格的覆盖视图,如上一段所述)。 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"