F#用不同的模板参数实现接口

时间:2014-04-05 10:37:06

标签: f#

拥有此代码:

type Point2D(x, y) =
    member this.X with get() = x
    member this.Y with get() = y

    interface System.IEquatable<Point2D> with
        member x.Equals point =
            x.X = point.X
            && x.Y = point.Y

type Point3D(x, y, z) =
    inherit Point2D(x, y)

    member this.Z with get() = z

    interface System.IEquatable<Point3D> with
        member x.Equals point =
            (x :> System.IEquatable<Point2D>).Equals point
            && x.Z = point.Z

http://take.ms/rjWlJ

我有编译时间。 F#不允许使用不同的模板参数实现相同的接口。但我想在派生类型中实现强类型的等号。那我该怎么办呢?

2 个答案:

答案 0 :(得分:3)

没有-可以-DO。这是一个有点令人遗憾的事态,因为当它来自不同的CLR语言时,F#可以完美地使用具有这种设计的类型。

我听到的解释是,拥有这样的功能并不重要,部分原因是因为这种类/接口重的设计不被认为是惯用的(我同意)。

所以你有一个选择是在C#中实现这些类型。

另一个更惯用的方法是将它们作为记录来实现:

type Point2D = { x: float; y: float }

type Point3D = { x: float; y: float; z: float }
    with 
        static member FromPoint2D (p: Point2D) = ...
        member this.ToPoint2D () = ...

也许添加一个模块,其中包含用于比较2d和3d的函数,它将为您封装转换。

答案 1 :(得分:2)

正如编译器错误所解释的那样,这是不受支持的,所以最好的解决办法可能是在这种情况下避免继承并添加一个成员来转换为2d点:

type Point3D(x, y, z) =
        member this.X with get() = x
        member this.Y with get() = y
        member this.Z with get() = z

        member this.As2D = new Point2D(this.X, this.Y)

        interface System.IEquatable<Point3D> with
            member x.Equals point =
                x.X = point.X && x.Y = point.Y && x.Z = point.Z