【问题标题】:F# Interface with static member带有静态成员的 F# 接口
【发布时间】:2020-04-18 15:24:33
【问题描述】:

如何在接口中定义静态成员?
为什么不可能?

我想强制 F# 类型(类)使用静态方法从字符串创建自身的实例(JSON 解析)。 我想要这个接口示例:

[<Interface>]
type public ILikeJson<'T> =
    abstract member ToJson: unit -> string         // OK
    static abstract member FromJson: string -> 'T  // <-- "static" is not valid here !

另外,来自字符串的构造函数也可以完成这项工作,但静态方法听起来更好,因为它会有一个合适的名称,而且我也不知道如何在接口中定义构造函数。

【问题讨论】:

    标签: interface f#


    【解决方案1】:

    当前的 CLR 规范声明接口仅针对对象实例实现,并不适用于类型本身。

    C# 8 提出了定义静态接口成员的建议,但需要在接口定义本身内提供静态方法的实现。因此,您将无法为每个类实现 FromJson 方法。

    如果你在 F# 中尝试这个,你会得到:

    FS0868:接口不能包含具体成员的定义。您可能需要在您的类型上定义一个构造函数来指示该类型是一个类。

    解决此问题的一种方法是使用static type constraints。它们允许您查找类型上是否存在方法。

    let inline create< ^T when ^T : (static member FromJson: string -> ^T)> json = 
         (^T : (static member FromJson: string -> ^T) (json))
    

    这支持任何具有静态方法FromJsonstring -&gt; T 签名的类型。

    type Number(num: double) =
        member _.Value = num
        static member FromJson (json) = new Number(Double.Parse(json))
    

    并使用:

    create<Number> "1.5" //creates a Number(1.5)
    

    【讨论】:

    • 谢谢,我还尝试了“inline”关键字,试图找到不同的解决方案,很有趣。我的目标是强制一堆类/类型公开相同的“ToJson”和静态“FromJson”方法。一种“强制命名约定”。错误使用接口,我完成了只是将这些方法直接添加到类/类型中,任何其他解决方案似乎都太麻烦了(也是因为 FromJson 将在 C# 中使用)。无论如何,有用的例子,谢谢。
    • 一个常见的模式是实现一个Parse 方法,该方法接受一个json字符串,它修改了类的字段。这类似于ISerializable所采取的方法。
    • 我不知道这样做的更高目的 - 但为了以特定方式序列化/反序列化类型,我一直实现自定义数据协定解析器。
    • 更高的目的实际上是 JSON 序列化的问题。 Newtonsoft 和 JIL 都无法序列化类型“OpenOrder”(alex75.visualstudio.com/_git/…),我不想添加参数构造函数(JIL 需要)。
    • 子元素构造函数(CurrencyPair 类型)中的 JsonContructor 属性也不起作用,通常我不想污染具有太多属性的类型。使用自定义 Serializer 类来管理从/到 JSON 解析该类型的字符串是我考虑过的另一种方法。现在,类(OpenOrder)实例中的两个特定方法将解决我的问题。感谢您的提示。
    猜你喜欢
    • 2011-01-24
    • 2023-03-16
    • 1970-01-01
    • 2010-11-10
    • 1970-01-01
    • 2013-01-13
    • 2020-12-20
    • 1970-01-01
    相关资源
    最近更新 更多