F # и интерфейсные элементы

У меня есть досадная ошибка.

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

Последняя строка, в частности "Имя", генерирует ошибку компилятора, указывающую, что "поле, конструктор или член" Имя "не определено".

Обходной путь, который я использовал, - написать

let name = (pluto :> Animal).Name

Однако это очень раздражает и создает много визуального шума. Есть ли что-то, что можно сделать в F #, чтобы просто разрешить Имя, не сообщая компилятору, что имя является производным членом из типа Animal?

Ответ 1

В F #, когда вы реализуете интерфейс, это эквивалент явной реализации интерфейса в С#. То есть вы можете вызвать метод через интерфейс, но не напрямую через класс.

Справочная статья F # о интерфейсах предлагает добавить метод, который повышает уровень готовности к типу:

type Dog (name : string) =

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

    interface Animal with
        member this.Name : string = name

Или, как предложил Даниэль, вы можете сделать это наоборот, а это значит, что вы можете избежать этого приведения:

type Dog (name : string) =

    member this.Name = name

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

Кроме того, соглашение .Net для имен интерфейсов должно начинаться с I, поэтому ваш интерфейс должен называться IAnimal.

Ответ 2

Другим вариантом является использование абстрактного класса вместо интерфейса:

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

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

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