具有多个构造函数语法的F#继承

Fra*_*ron 3 inheritance f# constructor

我有这个F#课

module File1

open System
open System.Collections.Generic

type TimeRangeList<'e>(getter: DateTime * DateTime -> List<'e>, ?maybe_tFrom: DateTime, ?maybe_tTo: DateTime) as this = 
    inherit List<'e>()
    //inherit List<'e>(getter(defaultArg maybe_tTo DateTime.Now, defaultArg maybe_tFrom ((defaultArg maybe_tTo DateTime.Now).AddDays(-1.0))))

    let tTo = defaultArg maybe_tTo DateTime.Now
    let tFrom = defaultArg maybe_tFrom (tTo.AddDays(-1.0))
    do this.AddRange(getter(tFrom, tTo))
Run Code Online (Sandbox Code Playgroud)

现在我想添加构造函数并使用此处的语法

type TimeRangeList<'e> = 
    inherit List<'e>
    val tFrom: DateTime
    val tTo: DateTime
    new (getter: DateTime * DateTime -> List<'e>, ?maybe_tFrom: DateTime, ?maybe_tTo: DateTime) = {
            inherit List<'e>()
            //inherit List<'e>(defaultArg maybe_tFrom ((defaultArg maybe_tTo DateTime.Now).AddDays(-1.0)), getter(defaultArg maybe_tTo DateTime.Now))

            tTo = defaultArg maybe_tTo DateTime.Now
            tFrom = defaultArg maybe_tFrom (tTo.AddDays(-1.0)) //tTo undefined
            //tFrom = defaultArg maybe_tFrom ((defaultArg maybe_tTo DateTime.Now).AddDays(-1.0))
        }
    do this.AddRange(getter(tFrom, tTo)) //primary constructor required
Run Code Online (Sandbox Code Playgroud)

这段代码给出了两个错误:

  1. 在'tFrom = ...'中它表示"未定义",而tTo明显在范围内; 作为一种解决方法,我可以重复defaultArg调用,如下面(注释)行所示.有没有更好的办法?
  2. 在调用'AddRange'的最后一行中,它抱怨只能在主构造函数中执行调用,这是公平的.但是,如何调用必要的AddRange来初始化列表?我尝试了不同的选择,但找不到方法.注释在注释的继承行中显示,但最后我反复冗余地调用defaultArg; 必须有一个更清晰,更优雅的方式

rmu*_*unn 5

这是您正在寻找的语法:

module File1

open System
open System.Collections.Generic

type TimeRangeList<'e> = 
    inherit List<'e>
    val tFrom: DateTime
    val tTo: DateTime
    new (getter: DateTime * DateTime -> List<'e>, ?maybe_tFrom: DateTime, ?maybe_tTo: DateTime) as this =
        let to_ = defaultArg maybe_tTo DateTime.Now
        let from_ = defaultArg maybe_tFrom (to_.AddDays(-1.0))
        {
            inherit List<'e>()

            tTo = to_
            tFrom = from_
        }
        then
            this.AddRange(getter(this.tFrom, this.tTo))
Run Code Online (Sandbox Code Playgroud)

文档链接:

为了解释一下,{ field = value; field2 = value2 }语法不一定是在定义辅助构造函数的块中找到的唯一表达式new().它只需要是最后一个表达式,即返回的表达式.(这里,即使从技术上讲,then块是构造函数中的"最后"块,它的返回值(必须是unit)也会被忽略,构造函数的实际返回值是块中找不到then的最后一个表达式).因此,可以安全地使用let先前的表达式来定义要放入类的字段中的值,并且这些let表达式可以像在普通代码中那样相互引用.因此,如果您需要将复杂或昂贵的计算放入多个字段中,您可以这样:

new () =
    let result = expensiveCalculationIWantToDoOnlyOnce()
    { field1 = result; field2 = result + 1; field3 = result + 2 }
Run Code Online (Sandbox Code Playgroud)