open FunctionalObjects // A record is like an interface type Printer = { PrintMessage : string -> unit } // Let's define a printHelloWorld function which uses the Printer interface. // // Notice that the type annotation is not required because Printer is a record // and F# can infer the type of the variable based on the PrintMessage field. // // Because this pattern uses a concrete type for the interface, no runtime // reflection is needed and type checking happens completely at compile time. let printHelloWorld (printer : Printer) = printer.PrintMessage "Hello World" // An instance of the record is a class aka an implementation of the interface let basePrinter : Printer = { PrintMessage = fun s -> printfn "Message: %s" s } printfn "Using the base printer:" printHelloWorld basePrinter // We can create a sub-class of the base printer using Object.derive // // Object.derive is simply // let derive f o = f o // so it's completely syntactic sugar let screamingPrinter : Printer = basePrinter |> Object.derive (fun b -> { b with // We choose which methods to override PrintMessage = fun s -> b.PrintMessage (s.ToUpper()) }) // printHelloWorld doesn't have to change when we switch the Printer. printfn "Using the screaming printer:" printHelloWorld screamingPrinter