在F#中定义静态类

时间:2012-10-27 16:31:34

标签: .net static f#

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

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

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

5 个答案:

答案 0 :(得分:32)

正如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#中那样添加实例方法,这种技术不会导致编译器错误,但从调用者的角度来看,没有区别。

答案 1 :(得分:4)

我不确定是否存在静态类。 &#39;静态&#39;我认为,在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

所以,你现在所做的就是做到这一点。

答案 2 :(得分:3)

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

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

关于第二种方法,它正是你所描述的旧问题的the accepted answer。我重构代码来解释它更容易。首先,定义虚拟单案例离散联合:

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-bound:

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

如果能够使用此方法重载let-bounds,则应创建一个包装器模块来保存这些函数并标记类型private

答案 3 :(得分:3)

The F# Component Design Guidelines中解释了这一点。

[<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#")

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

答案 4 :(得分:-4)

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