32

是否可以在 F# 中定义包含可重载成员的静态类?let模块绑定不能被重载,即使它们被编译成静态类中的静态成员。

typedeclerations 可以包含静态成员,但我不知道类型本身是否可以设为静态。

我目前的解决方案是type使用私有构造函数定义 a 并使用它。我想知道是否有一种方法可以根据需要定义静态类型。

4

5 回答 5

45

正如 Robert Jeppeson 所指出的,C# 中的“静态类”只是创建一个不能被实例化或继承的类的简写,并且只有静态成员。以下是在 F# 中完全实现这一点的方法:

[<AbstractClass; Sealed>]
type MyStaticClass private () =
    static member SomeStaticMethod(a, b, c) =
       (a + b + c)

    static member SomeStaticMethod(a, b, c, d) =
       (a + b + c + d)

这可能有点矫枉过正,因为AbstractClass私有构造函数和私有构造函数都会阻止您创建该类的实例,但是,这就是 C# 静态类所做的 - 它们被编译为具有私有构造函数的抽象类。该Sealed属性阻止您从此类继承。

如果以 C# 中的方式添加实例方法,此技术不会导致编译器错误,但从调用者的角度来看,没有区别。

于 2012-11-16T15:14:09.643 回答
9

这在F# 组件设计指南中进行了解释。

[<AbstractClass; Sealed>]
type Demo =
    static member World = "World"
    static member Hello() = Demo.Hello(Demo.World)
    static member Hello(name: string) = sprintf "Hello %s!" name

let s1 = Demo.Hello()
let s2 = Demo.Hello("F#")

仍然可以定义实例方法,但是当没有可用的构造函数时,您无法实例化该类。

2021 年 1 月编辑:查看 Abel 的评论和链接的问题。Joel Mueller 的回答似乎是迄今为止最好的建议,但未来情况可能会发生变化。

于 2016-12-25T18:49:41.957 回答
5

在 F#中没有定义静态类型的工具。

第一种选择是定义一个模块,但它缺乏重载函数的能力(这是你所追求的)。第二种选择是用静态成员声明一个普通类型。

关于第二种方法,这正是您对旧问题的公认答案所描述的。我重构了代码以更容易地解释它。首先,定义了一个虚拟的单案例可区分联合:

type Overloads = Overloads

其次,您利用了静态成员可以重载的事实:

type Overloads with
    static member ($) (Overloads, m1: #IMeasurable) = fun (m2: #IMeasurable) -> m1.Measure + m2.Measure 
    static member ($) (Overloads, m1: int) = fun (m2: #IMeasurable) -> m1 + m2.Measure

第三,使用inline关键字将这些重载方法的约束传播到 let-bounds:

let inline ( |+| ) m1 m2 = (Overloads $ m1) m2

当您能够使用此方法重载 let-bounds 时,您应该创建一个包装模块来保存这些函数并标记您的类型private

于 2012-10-27T16:45:09.523 回答
5

我不确定是否有静态类之类的东西。我相信,C# 中类级别的“静态”是在 2.0 中引入的,主要是为了方便(避免私有构造函数和编译时检查不存在实例成员)。您无法检查类型并得出结论它是静态的:http: //msdn.microsoft.com/en-us/library/system.reflection.typeinfo.aspx

更新:MSDN 声明一个静态类是一个密封的类,只有静态成员: http: //msdn.microsoft.com/en-us/library/79b3xss3 (v=vs.80).aspx

所以,你现在正在做的就是做它的方法。

于 2012-10-27T23:11:12.017 回答
-4

我认为这里的问题是试图将 F# 变成 C#。如果不能以非命令方式解决问题,请使用 C# 或编写面向对象的库并在 F# 中使用它。

于 2012-10-30T20:08:51.573 回答