How to implement interface in F#

Article ID: 2832106 - View products that this article applies to.

About Author:

Collapse this tableExpand this table
Collapse this imageExpand this image
MVP
 
This article is provided by MVP Eriawan Kusumawardhono. Microsoft is so thankful that MVPs who proactively share their professional experience with other users. The article would be posted on MVP's MVP's website or blog later.
Expand all | Collapse all

On This Page

Overview

F# is a multi paradigm programming language. It is a mix of functional programming language and object oriented programming language. It is also part of programming languages on top of .NET platform, and .NET class libraries are mostly object oriented.

Being as part of programming languages on top of .NET, F# has supports for OOP features. Common or fundamental OOP features inheritances, polymorphism, and encapsulations. Inheritances contains nice feature of OOP, class inheritances and implementations of interfaces. 

How to Create interface in F#

Interfaces in F# are implemented in two ways:
  1. Using object expressions
  2. Using class types
To create interfaces using class types are quite straightforward, the syntax is similar to interface declaration of C# and VB. 

This is the syntax using class types:

// Interface declaration:
[ attributes ]
type interface-name =
   [ interface ]
     abstract member1 : [ argument-types1 -> ] return-type1
     abstract member2 : [ argument-types2 -> ] return-type2
     ...
   [ end ]


This is a sample code of creating interfaces using class types (from F# in Visual Studio 2010 Tutorial template):

type IPeekPoke = 
    abstract Peek: unit -> int
    abstract Poke: int -> unit

The IPeekPoke will be treated as interface and will have the same signature as declaring interface in C# and VB. By default, the access modifier when not specified is public. This interface can also contain other members not just methods, but it can contain properties:

type IConnectionFactory =
    interface
        abstract ConnectionString : string with get, set
        abstract ConnectionState : int with get
        abstract Open : unit -> unit
        abstract Close : unit -> unit
    end

The interface declaration above can also be written to omit interface keyword that ending with end keyword:


type IConnectionFactory =
    abstract ConnectionString : string with get, set
    abstract ConnectionState : int with get
    abstract Open : unit -> unit
    abstract Close : unit -> unit

The type IConnectionFactory simulates a database connection commonly found in System.Data. It demonstrate an abstract property of ConnectionString with setter (set) and getter (get), ConnectionState that has getter only, and abstract method of Open and Close.

Note that F# clearly defines that each method that has no parameter and returns no parameter has to have signature as unit, returning no parameter as unit.

To create interface using object expressions, the interface are declared within a class. This is the syntax:

// Implementing, by using an object expression:
[ attributes ]
let class-name (argument-list) =
   { new interface-name with
       member self-identifier.member1 argument-list = method-body1
       member self-identifier.member2 argument-list = method-body2
       [ base-interface-definitions ]
   }
   member-list
This is a sample of interface implemented using object expressions:

let makePrintable(x: int, y: float) =
    { new IPrintable with
              member this.Print() = printfn "%d %f" x y }
let x3 = makePrintable(1, 2.0) 
x3.Print()

The advantages of using the object expression syntax are subtle: the interface does not have to be named and the scope of the interface is not visible from outside. Concrete implementation has to be implemented directly inside the class. But the disadvantage of using this syntax is quite clear; this syntax has no comparable features in C# and VB.

How to Create type that implements interfaces

To create types that implements interface, the interface must be declared using class type syntax.

For example, we can create type that implement IPeekPoke interface above:

// Types: classes with interface implementations
// ---------------------------------------------------------------
/// A widget which counts the number of times it is poked
type Widget(initialState:int) = 
    /// The internal state of the Widget
    let mutable state = initialState
    // Implement the IPeekPoke interface
    interface IPeekPoke with 
        member x.Poke(n) = state <- state + n
        member x.Peek() = state 
        
    /// Has the Widget been poked?
    member x.HasBeenPoked = (state <> 0)
Now, to call the method of the interface, F# requires the call to be explicit to specify the interface, and this is clearly specified in MSDN Library:

"Interface methods can be called only through the interface, not through any object of the type that implements the interface. Thus, you might have to upcast to the interface type by using the :> operator or the upcast operator in order to call these methods."
This is a sample code to call methods of IPeekPoke:

let widget = Widget(12) :> IPeekPoke
widget.Poke(4)
let peekResult = widget.Peek()
There is an alternative syntax to call interface method. An alternative is to declare a method on the object that upcasts and calls the interface method, as in the following example, with comparison of having an added sample of using upcast of above:


type IPrintable =
   abstract member Print : unit -> unit

type SomeClass1(x: int, y: float) =
   interface IPrintable with 
      member this.Print() = printfn "%d %f" x y

type SomeClass2(x: int, y: float) =
   member this.Print() = (this :> IPrintable).Print()
   interface IPrintable with 
      member this.Print() = printfn "%d %f" x y

// sample usage 
let x2 = new SomeClass2(1, 2.0)
x2.Print()
The code of SomeClass2 declaration define member Print that has upcast to IPrintable.Print and also has concrete implementations of Print method.


More information

For more information about interface in F#, please visit:

Interfaces (F#)

Community Solutions Content Disclaimer

MICROSOFT CORPORATION AND/OR ITS RESPECTIVE SUPPLIERS MAKE NO REPRESENTATIONS ABOUT THE SUITABILITY, RELIABILITY, OR ACCURACY OF THE INFORMATION AND RELATED GRAPHICS CONTAINED HEREIN. ALL SUCH INFORMATION AND RELATED GRAPHICS ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT AND/OR ITS RESPECTIVE SUPPLIERS HEREBY DISCLAIM ALL WARRANTIES AND CONDITIONS WITH REGARD TO THIS INFORMATION AND RELATED GRAPHICS, INCLUDING ALL IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, WORKMANLIKE EFFORT, TITLE AND NON-INFRINGEMENT. YOU SPECIFICALLY AGREE THAT IN NO EVENT SHALL MICROSOFT AND/OR ITS SUPPLIERS BE LIABLE FOR ANY DIRECT, INDIRECT, PUNITIVE, INCIDENTAL, SPECIAL, CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF USE, DATA OR PROFITS, ARISING OUT OF OR IN ANY WAY CONNECTED WITH THE USE OF OR INABILITY TO USE THE INFORMATION AND RELATED GRAPHICS CONTAINED HEREIN, WHETHER BASED ON CONTRACT, TORT, NEGLIGENCE, STRICT LIABILITY OR OTHERWISE, EVEN IF MICROSOFT OR ANY OF ITS SUPPLIERS HAS BEEN ADVISED OF THE POSSIBILITY OF DAMAGES.

Properties

Article ID: 2832106 - Last Review: September 25, 2013 - Revision: 5.1
Applies to
  • Microsoft Visual Studio Express 2012 for Web
  • Microsoft Visual Studio Premium 2012
  • Microsoft Visual Studio Professional 2012
  • Microsoft Visual Studio Ultimate 2012
Keywords: 
kbstepbystep kbmvp kbcommunity KB2832106

Give Feedback

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com