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