简体   繁体   中英

F# Interface with static member

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM