如何为某些类型共有的多个接口编写包装器类型

时间:2019-04-24 09:41:35

标签: generics f#

我想为不同类型编写一些通用代码,而无需为其创建一种基本类型。它的类型实现通用代码所需的多个接口。这是一种方法还是对f#类型模型不正确?

type IInterface1 =
    abstract member id :string

type IInterface2 = 
    abstract member weight :float

type A (id, weight) =
    interface IInterface1 with member x.id = id
    interface IInterface2 with member x.weight = weight

type B (id, weight) =
    interface IInterface1 with member x.id = id
    interface IInterface2 with member x.weight = weight

type Common<'T when 'T :> IInterface1 and 'T :> IInterface2> (o :'T) =
    interface IInterface1 with member x.id = o.id
    interface IInterface2 with member x.weight = o.weight

type LBranch<'T> (root :'T) =
    member val root = root
    member val branch = [root] :'T list with get, set
    member x.add item = x.branch <- item :: x.branch; x
    member x.head = match x.branch with h :: _ -> h | _ -> failwith "LevelingTree corrupt"

let a, b = A("1", 10.0), B("2", 100.0)
let ca, cb = Common(a), Common(b)
LBranch(ca).add(cb) // Common<B> is not compatible with Common<A>

我发现的简单解决方案不好,但是可以使用:

type Common (o :obj) =
    interface IInterface1 with member x.id = match o with :? IInterface1 as o -> o.id | _ -> failwith ""
    interface IInterface2 with member x.weight = match o with :? IInterface2 as o -> o.weight | _ -> failwith ""

1 个答案:

答案 0 :(得分:1)

一个真正简单的解决方案是让一个复杂的接口继承基本接口,即

type IInterface1 =
    abstract member id :string

type IInterface2 = 
    abstract member weight :float

type ICommon =
    inherit IInterface1
    inherit IInterface2

另请参阅MSDN