首页 文章

在F#中定义静态类

提问于
浏览
21

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

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

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

5 回答

  • 3

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

  • 31

    我'm not sure there is such a thing as a static class. ' static ' on class level in C# was introduced in 2.0, I believe, mostly as convenience (avoid private constructors and compile-time checking that no instance members are present). You can' t检查类型并得出它是静态的结论:http://msdn.microsoft.com/en-us/library/system.reflection.typeinfo.aspx

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

    那么,你现在所做的就是做到这一点 .

  • -4

    在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-bounds:

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

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

  • 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

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

相关问题