是否可以在 F# 中定义包含可重载成员的静态类?let
模块绑定不能被重载,即使它们被编译成静态类中的静态成员。
type
declerations 可以包含静态成员,但我不知道类型本身是否可以设为静态。
我目前的解决方案是type
使用私有构造函数定义 a 并使用它。我想知道是否有一种方法可以根据需要定义静态类型。
正如 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# 中的方式添加实例方法,此技术不会导致编译器错误,但从调用者的角度来看,没有区别。
这在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 的回答似乎是迄今为止最好的建议,但未来情况可能会发生变化。
在 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
。
我不确定是否有静态类之类的东西。我相信,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
所以,你现在正在做的就是做它的方法。
我认为这里的问题是试图将 F# 变成 C#。如果不能以非命令方式解决问题,请使用 C# 或编写面向对象的库并在 F# 中使用它。