Interfaces, Inheritance and Object Expressions

// Interfaces
type IShape =
    abstract Area: float
    abstract Name: string
    abstract Scale: float -> IShape

type Circle(r: float) =
    interface IShape with
        member _.Area = System.Math.PI * r * r
        member _.Name = "circle"
        member _.Scale k = Circle(r * k) :> IShape

let shape = Circle 2.0 :> IShape                  // upcast (interfaces are explicit in F#)
shape.Area

// Abstract classes and inheritance
[<AbstractClass>]
type Animal(name: string) =
    member _.Name = name
    abstract Speak: unit -> string
    default this.Describe() = $"{name} says {this.Speak()}"   // virtual method with default
    abstract Describe: unit -> string

type Dog(name) =
    inherit Animal(name)
    override _.Speak() = "Woof"

type Puppy(name) =
    inherit Dog(name)
    override this.Describe() = base.Describe() + " (squeaky)"

let animals: Animal list = [ Dog "Rex"; Puppy "Bit" ]
animals |> List.iter (fun a -> printfn "%s" (a.Describe()))

// Casting
let d = Dog "Rex"
let a = d :> Animal                               // upcast
let back = a :?> Dog                              // downcast (may throw InvalidCastException)
match a with :? Dog as dog -> dog.Speak() | _ 
…