如何在F#中编写抽象类派生类构造函数并初始化基类可变属性
解决方案
方案1:给基类添加带参数的构造函数(推荐)
让基类提供接受初始化值的构造函数,派生类通过调用该构造直接初始化私有字段,这种方式更符合封装原则,由基类控制自身字段的初始化逻辑:
[<AbstractClass>] type SomeBaseClass(?initialName: string) = // 用默认值处理可选参数,避免初始为空字符串 let mutable _name = defaultArg initialName "" member this.Name with get () = _name and set (value) = _name <- value abstract member Init : unit -> unit // 派生类调用基类带参构造完成初始化 type DerivedClassA() = inherit SomeBaseClass("DerivedClassA") override this.Init() = this.Name <- "DerivedClassA" // 若无需动态重置可移除Init方法 let derivedA = DerivedClassA() printfn "name = '%s'" derivedA.Name // 输出: name = 'DerivedClassA'
方案2:在派生类构造中使用as this引用实例
如果无法修改基类代码,可在派生类的主构造函数中添加as this声明,这样就能在do绑定中访问当前实例并设置属性:
[<AbstractClass>] type SomeBaseClass() = let mutable _name = "" member this.Name with get () = _name and set (value) = _name <- value abstract member Init : unit -> unit // 注意构造函数后的`as this`声明 type DerivedClassB() as this = inherit SomeBaseClass() // do绑定必须放在成员定义之前 do this.Name <- "DerivedClassB" override this.Init() = this.Name <- "DerivedClassB" let derivedB = DerivedClassB() printfn "name = '%s'" derivedB.Name // 输出: name = 'DerivedClassB'
之前尝试失败的原因
- DerivedClassB:
do绑定放在了成员定义之后,违反F#类型定义中let/do绑定必须先于成员的规则(错误FS0960)。 - DerivedClassC/D/E/F:派生类构造函数未添加
as this声明,导致do绑定中无法识别this;另外_name是基类的私有字段,派生类原本就无权直接访问,因此出现FS0939错误。
内容的提问来源于stack exchange,提问作者bookofproofs
相关产品推荐
相关产品推荐

