Defining static classes in F#

后端 未结 5 719
故里飘歌
故里飘歌 2021-02-12 03:56

Is it possible to define a static class that contains overloadable members in F#? let module bindings cannot be overloaded, even though they are compiled into stati

相关标签:
5条回答
  • 2021-02-12 04:02

    As Robert Jeppeson pointed out, a "static class" in C# is just short-hand for making a class that cannot be instantiated or inherited from, and has only static members. Here's how you can accomplish exactly that in 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)
    

    This might be a little bit of overkill, as both the AbstractClass and the private constructor will prevent you from creating an instance of the class, however, this is what C# static classes do - they are compiled to an abstract class with a private constructor. The Sealed attribute prevents you from inheriting from this class.

    This technique won't cause a compiler error if you add instance methods the way it would in C#, but from a caller's point of view there is no difference.

    0 讨论(0)
  • 2021-02-12 04:05

    This is explained in 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#")
    

    It is still possible to define instance methods, but you can't instantiate the class when there is no constructor available.

    edit Jan 2021 : See the comment from Abel, and the linked issue. Joel Mueller's answer seems to be the best advice so far, but things will perhaps change in the future.

    0 讨论(0)
  • 2021-02-12 04:08

    There is no facility for defining static types in F#.

    The first alternative is to define a module, but it lacks the capability of overloading functions (which is what you're after). The second alternative is to declare a normal type with static members.

    Regarding the second approach, it is exactly what the accepted answer to your old question described. I refactor the code to explain it easier. First, a dummy single-case discreminated unions is defined:

    type Overloads = Overloads
    

    Second, you exploit the fact that static members can be overloaded:

    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
    

    Third, you propagate constraints of these overloaded methods to let-bounds using inline keyword:

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

    When you're able to overload let-bounds using this method, you should create a wrapper module to hold these functions and mark your type private.

    0 讨论(0)
  • 2021-02-12 04:20

    I'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 examine the type and conclude that it is static: http://msdn.microsoft.com/en-us/library/system.reflection.typeinfo.aspx

    Update: MSDN declares a static class is a class that is sealed and has only static members: http://msdn.microsoft.com/en-us/library/79b3xss3(v=vs.80).aspx

    So, what you're doing at the moment is the way to do it.

    0 讨论(0)
  • 2021-02-12 04:26

    I think the problem here is trying to make F# into C#. If the problem can't be solved in a non imperative fashion use C# or write an object oriented library and use it in F#.

    0 讨论(0)
提交回复
热议问题