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#, чтобы иметь возможность разрешать Name, не сообщая компилятору явно, что Name является производным от типа Animal?
2 ответа
В F#, когда вы реализуете интерфейс, это эквивалент явной реализации интерфейса в C#. То есть вы можете вызывать метод через интерфейс, но не напрямую через класс.
Справочная статья 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
,
Другой вариант - использовать абстрактный интерфейс вместо интерфейса:
[<AbstractClass>]
type Animal () =
abstract Name : string
type Dog (name) =
inherit Animal()
override dog.Name = name
let pluto = Dog("Pluto")
let name = pluto.Name