简体   繁体   中英

F# class implements interface as private member, why?

I decided to practice with F# today and found one interesting thing. I shall provide the similar code both in C# and F#, but with rather different behavior using DAO (Data access object):

C# version:

interface IPoint2D
{
    int X { get; set; }
    int Y { get; set; }
}

class Point2D : IPoint2D
{
    private int _x = 0;
    private int _y = 0;

    public int X { get { return _x; } set { _x = value; } }
    public int Y { get { return _y; } set { _y = value; } }
}

F# version:

type IPoint2D =
    abstract member X: int
    abstract member Y: int

type Point2D(x: int, y: int) = 
    let _x = 0
    let _y = 0

    interface IPoint2D with
        member this.X = x
        member this.Y = y

The 1st difference, which is very visible, that using C#, I must declare members as public for implementation contract.

But, why is F# allowing to implement the interface as private member? What's the sense?

在此处输入图片说明

F# requires objects to be upcast in order to directly access their interfaces. let x = (firstPoint :> IPoint2D).X

F# does support implicit interface casting for function parameters. It used to require generics but has been update in newer versions of the language.

let Distance (a:IPoint2D) (b:IPoint2D) =
    (a.X - b.X) * (a.X - b.X) + (a.Y - b.Y) * (a.Y - b.Y)
    |> float |> Math.Sqrt

let firstPoint = new Point2D(2, 3)
let secondPoint = new Point2D(4, 5)

let distance = Distance firstPoint secondPoint
printf "%f" distance

Not everyone agrees but as a design rule objects shouldn't be upcasted to access their interfaces directly. Doing so increases code coupling. If code is written that calls methods on an objects interfaces, that objects class can't be easily changed without updating all of the call sights.

What if the interface was IPoint3D with x,y,z and you wanted to changed it to IPoint2D, all casts that reference z would have to be updated instead of just interface consumers like Distance.

I believe this design choice was done for consistency with the rest of the language and to foster looser coupling while using OOP. There is a user voice feature request from 2014 that has gone unanswered requesting implicit upcasting.

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