为什么不能在scala中覆盖可变变量?
class Abs(var name: String){
}
class AbsImpl(override var name: String) extends Abs(name){
}
上面的代码给出了以下编译时错误: -
variable name cannot override a mutable variable
如果name声明为val,则上面的代码可以正常工作。
答案 0 :(得分:4)
如果您可以使用var覆盖var,则覆盖成员可以具有更窄的类型。 (这就是如何定义覆盖。)
然后你可以指定一个更宽类型的值,然后读取它,期望更窄的类型,然后失败。
所涉及的二传手的插图:
scala> class A ; class B extends A
defined class A
defined class B
scala> abstract class C { var x: A } ; class D extends C { var x: B = _ }
<console>:13: error: class D needs to be abstract, since variable x in class C of type A is not defined
(Note that an abstract var requires a setter in addition to the getter)
abstract class C { var x: A } ; class D extends C { var x: B = _ }
^
scala> abstract class C { var x: A }
defined class C
scala> class D extends C { var x: B = _ ; def x_=(a: A) = ??? }
defined class D
答案 1 :(得分:3)
简短回答:您需要将-Yoverride-vars
传递给Scala编译器。
根据规范,var
既是getter又是setter,正常的覆盖规则适用于这些方法。然而,这被证明会产生一些不良后果w.r.t.到final
关键字和内联。编译器中的代码提到了一些需要澄清的规范:
// TODO: this is not covered by the spec. We need to resolve this either by changing the spec or removing the test here.
if (!settings.overrideVars)
overrideError("cannot override a mutable variable")
相关票证:SI-3770
答案 2 :(得分:1)
我认为目的只是设置继承的var name
的值。这可以通过这种方式实现(没有override var
):
class Abs(var name: String){
}
class AbsImpl(name: String) extends Abs(name){
}
歧义来自于name: String
中的本地变量AbsImpl
,该变量以var name: String
中的继承Abs
命名。类似的代码,语法不明确,但也不那么优雅:
class Abs(var name: String){
}
class AbsImpl(name_value: String) extends Abs(name_value){
}
答案 3 :(得分:1)
当你想要覆盖一个var,它等同于尝试覆盖java中不可能的字段。
答案 4 :(得分:0)
当您尝试覆盖的var
已经有作业时会发生这种情况。我不确定为什么这是禁止的,但它也没什么意义。
将name
定义为抽象而非
trait Abs {
var name: String
}
class AbsImpl(name0: String) extends Abs {
var name = name0
}
或
trait Abs {
var name: String
}
class AbsImpl(private var name0: String) extends Abs {
def name = {
println("getter")
name0
}
def name_=(value: String) = {
println("setter")
name0 = value
}
}