此主题已在之前讨论过,但未得到满意答复(在我看来)。 请考虑以下scala代码:
class A(a:Int) { val _a=a }
class A1(val a:Int) { val _a=a }
class B(a:Int) extends A(a) // OK
class C(val a:Int) extends A(a) // OK
class B1(a:Int) extends A1(a) // OK
class C1(val a:Int) extends A1(a) // fails
class D1(override val a:Int) extends A1(a) // OK
我认为将class参数声明为val只会对构造函数调用产生影响: 复制参数而不是传递引用。但是,在每种情况下,类字段都被分配为val。这是对的吗?
现在我不明白为什么我们需要在最后一行使用override关键字。 请注意,我们不会将类声明为案例类,因此不会自动分配字段。
最后有一个很好的理由为什么人们甚至想要用val来定义像A1这样的类 class parameter?
提前感谢所有回复。
答案 0 :(得分:6)
我认为将class参数声明为val只有一个 对构造函数调用的影响:复制参数而不是 传递参考。但是,在每种情况下都会分配类字段 作为一个val。这是对的吗?
完全没有。
如果构造函数中存在val或var,则会导致在类中声明相同名称的val或var,并在构造时为其指定构造函数参数。否则,如果构造函数参数在初始化之外使用,即在方法中,则仍可在类中创建(私有)val。
在A1类中,成员_a真的没用,因为如果你写
class A1(val a: Int) {}
等同于
class A1(someFreshName: Int) {val a = someFreshName}
所以在C1
中,你试图声明一个新成员a,而已经有一个成员。因此覆盖。
在您的特定实例中,两个成员都具有相同的值,但您可以做(可能不是一个好主意)
class C1(override val a: Int) extends A1(12)
然后,新成员a
将构造函数参数作为值,而前一个a
将具有值12并被隐藏(但仍然,A1
中编写的代码将访问它)。