首页 文章

为什么不能在scala中覆盖可变变量?

提问于
浏览
14

为什么不能在scala中覆盖可变变量?

class Abs(var name: String){
}

class AbsImpl(override var name: String) extends Abs(name){
}

上面的代码给出了以下编译时错误: -

variable name cannot override a mutable variable

If name is declared val, then above code works fine.

5 回答

  • 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

    简短的回答:您需要将 -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

  • 3

    我相信意图只是设置继承的 var name 的值 . 这可以通过这种方式实现(没有 override var ):

    class Abs(var name: String){
    }
    
    class AbsImpl(name: String) extends Abs(name){
    }
    

    这种歧义来自于 AbsImpl 中的本地var name: String ,它是从 Abs 继承的 var name: String 命名的 . 一个类似的代码,在语法上不那么模糊,但也不那么优雅:

    class Abs(var name: String){
    }
    
    class AbsImpl(name_value: String) extends Abs(name_value){
    }
    
  • 1

    当你想覆盖var等同于尝试覆盖java中不可能的字段时 .

  • 0

    当您尝试覆盖的 var 已经具有分配时,会发生这种情况 . 我不确定为什么这是被禁止的,但也没什么意义 .

    另见this question .

    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
      }
    }
    

相关问题