抽象类主构造器含默认值不可变变量,子类如何实现双构造器赋值?
解决Scala抽象类子类不可变变量的构造器问题
这个问题的核心在于不可变变量(val)一旦初始化就无法修改,所以你不能先让父类用默认值初始化someVal,再试图在子类的辅助构造器里改变它——这完全违背了val的设计初衷。下面是正确的实现方式:
第一步:定义抽象类
首先你的抽象类主构造器的定义是没问题的,带默认值的不可变变量:
abstract class BaseClass(val someVal: String = "defaultVal")
第二步:正确实现子类
要同时支持SubClass()和SubClass("anotherVal")两种实例化方式,你需要让子类的主构造器直接接收参数(并设置默认值),然后把这个参数传递给父类的主构造器。这样父类的someVal在初始化时就拿到了正确的值,完全符合不可变的要求:
class SubClass(someVal: String = "defaultVal") extends BaseClass(someVal)
为什么这样可行?
- 当你调用
SubClass()时,子类主构造器使用默认值"defaultVal",并把它传给父类的主构造器,父类的someVal就初始化为默认值。 - 当你调用
SubClass("anotherVal")时,子类把自定义值传给父类,父类的someVal直接初始化为这个自定义值。 - 父类的
someVal是不可变的,子类继承了这个属性,全程没有任何修改操作,完全符合要求。
可选:显式override父类的val
如果你想让子类自己也显式拥有这个someVal属性(其实父类已经提供了,子类可以直接访问),可以加上override关键字:
class SubClass(override val someVal: String = "defaultVal") extends BaseClass(someVal)
效果和上面的实现完全一致,只是更明确地表明你重写了父类的val属性。
测试代码
验证一下两种实例化方式的效果:
val sc = SubClass() println(sc.someVal) // 输出: defaultVal val sc2 = SubClass("anotherVal") println(sc2.someVal) // 输出: anotherVal
为什么之前的实现会报错?
如果你之前尝试用子类的辅助构造器来实现,比如:
class SubClass extends BaseClass { def this(someVal: String) = { this() // 先调用主构造器,父类已经用默认值初始化了someVal // 这里试图修改someVal?不可能,因为它是val } }
这种写法必然报错,因为父类的someVal在调用this()时已经被初始化为默认值,而val是不可变的,你没有任何办法再修改它。这也是为什么必须在父类初始化时就传递正确的值。
内容的提问来源于stack exchange,提问作者codependent
相关产品推荐
相关产品推荐

