Eyvind
Eyvind

Reputation: 5261

F# interfaces and properties

I'm trying to get a grip on F#, and in the process I am converting some C# code. I'm having some trouble with defining properties in an interface and implementing them in a type.

Consider the following code:

module File1

type IMyInterface =
    abstract member MyProp : bool with get, set
    abstract member MyMethod : unit -> unit

type MyType() = 
    interface IMyInterface with
        member val MyProp = true with get, set
        member self.MyMethod() = if MyProp then () else ()

The documentation for F# properties appears to state that my implementation of MyProp in MyType is correct, however, the compiler complains that "The value or constructor 'MyProp' is not defined". Any ideas?

Upvotes: 13

Views: 5023

Answers (3)

Grundoon
Grundoon

Reputation: 2764

If you are only accessing the interface, then you don't need to define members in the type itself. Phil's answer is good if you want minimalism, but another approach I like is to use "let-bound" values rather than members -- for more complex code, type inference is better and they are generally easier to deal with than members.

type MyType() = 
    let mutable myProp = true 
    let myMethod() = if myProp then () else ()

    interface IMyInterface with
        member __.MyProp with get() = myProp and set v = myProp <- v
        member __.MyMethod() = myMethod()

The code is slightly cleaner than member versions as well, imo, because the self tag in type MyType() as self is only needed to access members -- let-bound values can be accessed directly from the interface.

Upvotes: 13

Phillip Trelford
Phillip Trelford

Reputation: 6543

To access the property within an (explicit) interface you need to cast to the self reference to the interface type:

type MyType() = 
    interface IMyInterface with
        member val MyProp = true with get, set
        member self.MyMethod() = if (self :> IMyInterface).MyProp then () else ()

You get the same error in C# if you implement the interface explicitly, and a cast is also required to access the member:

interface IMyInterface
{
    bool MyProp { get; set; }
    void MyMethod();
}

class MyType : IMyInterface
{
    bool IMyInterface.MyProp { get; set; }

    void IMyInterface.MyMethod()
    {
        if (((IMyInterface)this).MyProp) { }
    }
}

Upvotes: 20

Random Dev
Random Dev

Reputation: 52280

here is a working version:

type IMyInterface =
    abstract member MyProp : bool with get, set
    abstract member MyMethod : unit -> unit

type MyType() = 
    member val MyProp = true with get, set
    member self.MyMethod() = if self.MyProp then () else ()
    interface IMyInterface with
        member self.MyProp with get () = self.MyProp and set v = self.MyProp <- v
        member self.MyMethod() = self.MyMethod()

please note that I included the explicit members as you surely would have missed them ;)

Upvotes: 5

Related Questions