是否可以在F#中定义包含可重载成员的静态类? let
模块绑定不能重载,即使它们被编译为静态类中的静态静态成员。
type
declerations可以包含静态成员,但我不知道类型本身是否可以变为静态。
我目前的解决方案是使用私有构造函数定义type
并使用它。我想知道是否有一种方法可以根据需要定义静态类型。
答案 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#中使用它。