F# Training
F# Training
F# Training
  • Presentation
  • Fundamentals
    • Introduction
    • Syntax
      • Bases
      • Functions
      • Rules
      • Exceptions
    • First concepts
    • šŸ”Quiz
  • Functions
    • Signature
    • Concepts
    • Syntax
    • Standard functions
    • Operators
    • Addendum
    • šŸ”Quiz
    • šŸ“œSummary
  • Types
    • Overview
    • Tuples
    • Records
    • Unions
    • Enums
    • Anonymous records
    • Value types
    • šŸ“œRecap
    • Addendum
  • Monadic types
    • Intro
    • Option type
    • Result type
    • Smart constructor
    • šŸš€Computation expression (CE)
    • šŸš€CE theoretical basements
    • šŸ“œRecap
  • Pattern matching
    • Patterns
    • Match expression
    • Active patterns
    • šŸš€Fold function
    • šŸ“œRecap
    • šŸ•¹ļøExercises
  • Collections
    • Overview
    • Types
    • Common functions
    • Dedicated functions
    • šŸ”Quiz
    • šŸ“œRecap
  • Asynchronous programming
    • Asynchronous workflow
    • Interop with .NET TPL
    • šŸ“œRecap
  • Module and Namespace
    • Overview
    • Namespace
    • Module
    • šŸ”Quiz
    • šŸ“œRecap
  • Object-oriented
    • Introduction
    • Members
    • Type extensions
    • Class, Struct
    • Interface
    • Object expression
    • Recommendations
Powered by GitBook
On this page
  • Syntax
  • Implementation
  • Default implementation
  • F♯ interface is explicit
  • Implementing a generic interface
  • Inheritance

Was this helpful?

Edit on GitHub
  1. Object-oriented

Interface

Syntax

Similar to an abstract class but with only abstract members.

Atttribute:

  • [<AbstractClass>] attribute can not be used to declare an interface

  • [<Interface>] attribute is optional but recommended in most cases

type [accessibility-modifier] interface-name =
    abstract memberN : [ argument-typesN -> ] return-typeN
  • Interface name begins with I to follow .NET convention

  • Arguments can be named (without parentheses otherwise šŸ’„)

[<Interface>]
type IPrintable =
    abstract member Print : format: string -> unit

You can also use verbose syntax with an interface ... end block. → Not idiomatic except in the case of a member-less interface a.k.a marker interface.

type IMarker = interface end

Implementation

2 ways of implementing an interface:

  1. In an object expression šŸ“

  2. In a type (as in C♯)

type IPrintable =
    abstract member Print : unit -> unit

type Range = { Min: int; Max: int } with
    interface IPrintable with
        member this.Print() = printfn $"[{this.Min}..{this.Max}]"

Keyword

This interface F♯ keyword matches the implements keyword in Java and TypeScript.

Default implementation

F♯ 5.0 supports interfaces defining methods with default implementations written in C♯ 8+ but does not allow them to be defined directly in F♯.

Keyword

Don't confuse with default keyword: it's supported only in classes!

F♯ interface is explicit

F♯ interface implementation ≔ Explicit implementation of an interface in C♯

→ Interface methods are accessible only by upcasting:

[<Interface>]
type IPrintable =
    abstract member Print : unit -> unit

type Range = { Min: int; Max: int } with
    interface IPrintable with
        member this.Print() = printfn $"[{this.Min}..{this.Max}]"

let range = { Min = 1; Max = 5 }
(range :> IPrintable).Print()  // upcast operator
// [1..5]

Implementing a generic interface

[<Interface>]
type IValue<'T> =
    abstract member Get : unit -> 'T

// Contrived example for demo purpose
type DoubleValue(i, s) =
    interface IValue<int> with
        member _.Get() = i

    interface IValue<string> with
        member _.Get() = s

let o = DoubleValue(1, "hello")
let i = (o :> IValue<int>).Get() // 1
let s = (o :> IValue<string>).Get() // "hello"

Inheritance

Defined with inherit keyword

type A(x: int) =
    do
        printf "Base (A): "
        for i in 1..x do printf "%d " i
        printfn ""

type B(y: int) =
    inherit Base(y * 2) // šŸ‘ˆ
    do
        printf "Child (B): "
        for i in 1..y do printf "%d " i
        printfn ""

let child = B(1)
// Base: 1 2
// Child: 1
// val child: B
PreviousClass, StructNextObject expression

Last updated 1 month ago

Was this helpful?