F# and interface-implemented members
Asked Answered
P

2

17

I have a vexing error.

type Animal =

    abstract member Name : string

type Dog (name : string) =

    interface Animal with

        member this.Name : string =
            name

let pluto = new Dog("Pluto")
let name = pluto.Name

The last line, specifically "Name" generates a compiler error saying that "the field, constructor or member 'Name' is not defined".

The workaround I've used is to write

let name = (pluto :> Animal).Name

However this is very annoying and creates a lot of visual noise. Is there something one can do in F# to just be able to resolve Name without telling the compiler explicitly that Name is a derived member from the Animal type?

Pipeline answered 29/1, 2013 at 23:8 Comment(0)
D
26

In F#, when you implement an interface, it's an equivalent of explicit interface implementation in C#. That is, you can call the method through the interface, but not directly through the class.

F# reference article about interfaces suggests adding a method that does the upcasting to the type:

type Dog (name : string) =

    member this.Name = (this :> Animal).Name

    interface Animal with
        member this.Name : string = name

Or, as suggested by Daniel, you can do it the other way around, which means you can avoid that cast:

type Dog (name : string) =

    member this.Name = name

    interface Animal with
        member this.Name : string = this.Name

Also, the .Net convention for interface names is to start them with I, so your interface should be called IAnimal.

Desiccant answered 29/1, 2013 at 23:29 Comment(1)
If you put the logic in the class member and call it from the interface implementation you can avoid the cast. I think it also makes more sense conceptually.Solfatara
Q
7

Another option is to use an abstract class instead of an interface:

[<AbstractClass>]
type Animal () =
    abstract Name : string

type Dog (name) = 
    inherit Animal()
    override dog.Name = name

let pluto = Dog("Pluto")
let name = pluto.Name
Quattrocento answered 31/1, 2013 at 8:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.