Interfaces and Classes in F#

Interfaces

Interfaces are declared in a similar fashion to classes but with only abstract members, for example

type ICalculator =
    abstract member Add : int -> int -> int

Classes

type Calculator() =
    member this.Add a b = a + b

Here we declared a constructor with no arguments, but we could also declare a constructor which takes arguments, such as

type Calculator(a, b) =
        member this.Add = a + b

We can also declare the constructors in the following manner

type Calculator1 =
        new () = {}
        member this.Add = a + b

type Calculator2 =
        new (a, b) = { (* do something with the values *) }
        member this.Add = a + b

Leading on from this way of declaring constructors, we can also declare multiple constructors in the following manner

type SomeClass =
    val data : string
    new () = { data = "undefined"}
    new (d) = { data = d }

Here we’ve declared a default constructor and one which takes a single argument.

or implementing the previously declared ICalculator we have

type Calculator() =
    interface ICalculator with
        member this.Add a b = a + b

To access the Add method we need to cast our value to the specific interfaces, for example

let calc = new Calculator()
(calc :> ICalculator).Add 2 3

The :> is the cast operator.

We can also implement an interface in an anonymous class, for example

let calculator() =
   {
      new ICalculator with
         member this.Add a b = a + b
   }

Inheritance

type Calculator() =
   member this.Add a b = a + b

type NewCalculator() = 
   inherit Calculator()   

Virtual functions

To declare a function as virtual we need to both declare it as abstract and create a default implementation, for example

type MyClass() = 
   abstract member myfunction : unit -> unit
   default u.myfunction() = printfn "hello"

Note: the “u.” part of the above is a self identifier. Unlike C# which has the implicit “this” identifier, we can define whatever name we wish for the self identifier

We can define a self identifier at the class level using

type MyClass() as myself = 
   abstract member myfunction : unit -> unit
   default myself.myfunction() = printfn "hello"