Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 253
Eyvind Avatar asked Aug 05 '15 07:08

Eyvind


3 Answers

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) { }
    }
}
like image 116
Phillip Trelford Avatar answered Nov 01 '22 21:11

Phillip Trelford


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.

like image 27
Grundoon Avatar answered Nov 01 '22 22:11

Grundoon


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 ;)

like image 41
Random Dev Avatar answered Nov 01 '22 21:11

Random Dev