Interfaces and F # Properties

I am trying to capture F # and in this process I am converting C # code. I am having problems 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 the F # properties states that my MyProp implementation in MyType is correct, however, the compiler complains that "The value or constructor of" MyProp "is not defined." Any ideas?

+7
interface f #
source share
3 answers

To access a property in an (explicit) interface, you need to pass 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 explicitly implement the interface, and casting 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) { } } } 
+13
source share

If you are only accessing an interface, you do not need to define members in the type itself. Phil’s answer is good if you want minimalism, but a different approach. I like to use “let-bound” values ​​rather than members - for more complex code it's better to use type inference and they are usually easier to deal with 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 a little cleaner than the member versions, like imo, because the self tag in type MyType() as self is only required to access the elements. Available values ​​can be accessed directly from the interface.

+6
source share

here is the 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() 

note that I included explicit members as you would probably skip them;)

+4
source share

All Articles