【问题标题】:Overriding static properties in F# with extension methods使用扩展方法覆盖 F# 中的静态属性
【发布时间】:2018-01-03 22:01:31
【问题描述】:

可以在与现有实例和静态方法具有相同名称和类型签名的类型上定义 F# 扩展方法,以有效地覆盖这些方法的默认实现,但是我无法让它在静态属性上工作。

特别是,我正在尝试为DateTime 创建一个扩展方法,该方法返回更精确的时间,如下所示:

#nowarn "51"

open System

module DateTimeExtensions =

    open System.Runtime.InteropServices

    [<DllImport("Kernel32.dll", CallingConvention = CallingConvention.Winapi)>]
    extern void private GetSystemTimePreciseAsFileTime(int64*)

    type System.DateTime with
        // example showing that static methods can be overridden
        static member IsLeapYear(_: DateTime) =
            printfn "Using overridden IsLeapYear!"
            true

        // more accurate UtcNow method (note: not supported by older OS versions)
        static member UtcNow =
            printfn "Using overridden UtcNow!"
            let mutable fileTime = 0L
            GetSystemTimePreciseAsFileTime(&&fileTime)
            DateTime.FromFileTimeUtc(fileTime)

但是执行时的输出

open DateTimeExtensions
let _ = DateTime.IsLeapYear(DateTime.UtcNow)

只是

Using overridden IsLeapYear!

这表明静态方法“覆盖”正在工作,但不是静态属性。

(注意:我使用的是 F# 4.0)

【问题讨论】:

  • 你有什么理由想让它工作吗?由于这仅适用于导入您的模块的代码,因此您最好使用一个不同命名的函数。

标签: f#


【解决方案1】:

这个说法似乎不正确:

F# 扩展方法可以在具有相同名称的类型上定义,并且 类型签名作为现有实例和静态方法来有效 覆盖这些方法的默认实现,但是我不能 让它在静态属性上工作。

不,它们不会覆盖。

您可能会感到困惑,因为实际上您的IsLeapYear 签名是错误的,它应该采用整数,这就是它起作用的原因我的意思是您没有覆盖任何东西,只是添加了一个新的(扩展)方法。

如果您尝试使用原始签名,您会发现它也不起作用:

type System.DateTime with
    // example showing that static methods can NOT be overridden
    static member IsLeapYear(_: int) =
        printfn "Using overridden IsLeapYear!"
        false

> DateTime.IsLeapYear(2000);;
val it : bool = true

这与静态属性扩展的行为一致。

无论如何,我不确定为什么决定不覆盖,如果在设计语言时有这样的决定。我认为这将是一个有趣的功能,如果有充分的理由不实现它,至少它应该发出一个警告,说由于该方法已经存在,它将永远不会被调用。

也许我会针对 F# 编译器提出问题或建议。

【讨论】:

猜你喜欢
  • 2016-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多