Интерфейс F # с участником stati c - PullRequest
2 голосов
/ 18 апреля 2020

Как определить элемент stati c в интерфейсе?
Почему это невозможно?

Я хочу, чтобы тип (класс) F # имел метод stati c для создать экземпляр себя из строки (JSON синтаксический анализ). Я хочу этот пример интерфейса:

[<Interface>]
type public ILikeJson<'T> =
    abstract member ToJson: unit -> string         // OK
    static abstract member FromJson: string -> 'T  // <-- "static" is not valid here !

В качестве альтернативы конструктор из строки может сделать работу, но метод stati c звучит лучше, потому что у него будет подходящее имя, и я не знаю, как определить конструктор в интерфейсе тоже.

1 Ответ

2 голосов
/ 18 апреля 2020

В настоящей спецификации CLR говорится, что интерфейсы реализованы только для объектов экземпляров и не применяются к самим типам.

C# 8 содержит предложение по определению элементов интерфейса stati c, но необходимо предоставить реализацию методов stati c в самом определении интерфейса. Таким образом, вы не сможете реализовать FromJson метод для каждого класса.

Если вы попробуете это в F #, вы получите:

FS0868: Интерфейсы не могут содержать определения конкретных членов. Вам может потребоваться определить конструктор для вашего типа, чтобы указать, что тип является классом.

Одним из решений этой проблемы является использование stati c ограничений типа . Они позволяют вам искать существование метода для типа.

let inline create< ^T when ^T : (static member FromJson: string -> ^T)> json = 
     (^T : (static member FromJson: string -> ^T) (json))

Это поддерживает любой тип, имеющий метод c stati FromJson с сигнатурой string -> T.

type Number(num: double) =
    member _.Value = num
    static member FromJson (json) = new Number(Double.Parse(json))

и использовать:

create<Number> "1.5" //creates a Number(1.5)
...