How to define a static member in an Interface?
Why it is not possible?
I want to force a F# type (class) to have a static method to create an instance of itself from a string (JSON parsing). I want this Interface example:
[<Interface>]
type public ILikeJson<'T> =
abstract member ToJson: unit -> string // OK
static abstract member FromJson: string -> 'T // <-- "static" is not valid here !
Alternatively a constructor from a string can do the work but a static method sounds better because it will have an appropriate name and I don't know how to define a constructor in the Interface too.
The present CLR specification states that interfaces are only implemented for object instances and do not apply for the types themselves.
C# 8 has a proposal for defining static interface members, but it is required to provide an implementation for the static methods within the interface definition itself. So you won't be able to implement a FromJson
method per class.
If you try this in F#, you'll get:
FS0868: Interfaces cannot contain definitions of concrete members. You may need to define a constructor on your type to indicate that the type is a class.
One solution to this problem is to use static type constraints. They allow you to look up the existence of a method on a type.
let inline create< ^T when ^T : (static member FromJson: string -> ^T)> json =
(^T : (static member FromJson: string -> ^T) (json))
This supports any type which has a static method FromJson
with the string -> T
signature.
type Number(num: double) =
member _.Value = num
static member FromJson (json) = new Number(Double.Parse(json))
and to use:
create<Number> "1.5" //creates a Number(1.5)