F#在抽象类中部分实现了接口

时间:2016-02-28 22:48:26

标签: interface f# abstract-class

我正在尝试编写一个部分实现接口的抽象类。我还想为未实现的值设置默认值。似乎F#可能不支持这一点,但同样可能的是我不能使语法正确。任何帮助,将不胜感激。这就是我到目前为止所处的位置:

type IDrawable =
    abstract member Position : Vector2
    abstract member ShortSymbol : int
    abstract member ForeColor : string
    abstract member BackColor : string
    abstract member Symbol : char
    abstract member Description : string

[<AbstractClass>]
type DrawableBase(position, shortSymbol, foreColor, backColor) =

    let position : Vector2 = position
    let shortSymbol : int = shortSymbol
    let foreColor : string = foreColor
    let backColor : string = backColor

    interface IDrawable with
        member this.Position = position
        member this.ShortSymbol = shortSymbol
        member this.ForeColor = foreColor
        member this.BackColor = backColor

        default this.Symbol = char this.ShortSymbol
        default this.Description = ""

    new(oldBase: DrawableBase, newPosition) = DrawableBase(newPosition, oldBase.ShortSymbol, oldBase.ForeColor, oldBase.BackColor)  

这是一个学习项目,因此大部分内容并不重要 - 我也可能在这里做其他一些错误 - 随意批评。

2 个答案:

答案 0 :(得分:1)

我没有听说过部分接口实现,即使我在F#中使用类型继承和接口完成了一些OOP工作。您可以在基类的虚拟成员中获得相同的结果:

type IDrawable =
    abstract member Position : Vector2
    abstract member ShortSymbol : int
    abstract member ForeColor : string
    abstract member BackColor : string
    abstract member Symbol : char
    abstract member Description : string

[<AbstractClass>]
type DrawableBase(position, shortSymbol, foreColor, backColor) =

    let position : Vector2 = position
    let shortSymbol : int = shortSymbol
    let foreColor : string = foreColor
    let backColor : string = backColor

    abstract member Symbol : char
    default this.Symbol = char shortSymbol
    abstract member Description : string
    default this.Description = ""

    interface IDrawable with
        member this.Position = position
        member this.ShortSymbol = shortSymbol
        member this.ForeColor = foreColor
        member this.BackColor = backColor

        member this.Symbol = this.Symbol
        member this.Description = this.Description

因为F#中的接口是显式的,所以我更喜欢将所有接口成员实现为对相应类型成员的调用。例如。在前面的例子中,构造函数抱怨oldBase没有我添加的两个虚拟成员之外的成员:

new(oldBase: DrawableBase, newPosition) = DrawableBase(newPosition, oldBase.ShortSymbol, oldBase.ForeColor, oldBase.BackColor) 

一种解决方案是将oldBase的类型更改为IDrawable

new(oldBase: IDrawable, newPosition) = DrawableBase(newPosition, oldBase.ShortSymbol, oldBase.ForeColor, oldBase.BackColor) 

另一种解决方案是将所有方法添加到类型本身。这样更方便,因为它允许避免在许多地方进行显式转换,并以C#方式使用类(其中接口是隐式实现的),而不需要在需要调用接口成员的每个地方烦恼:>

[<AbstractClass>]
type DrawableBase(position, shortSymbol, foreColor, backColor) =

    let position : Vector2 = position
    let shortSymbol : int = shortSymbol
    let foreColor : string = foreColor
    let backColor : string = backColor

    member this.Position = position
    member this.ShortSymbol = shortSymbol
    member this.ForeColor = foreColor
    member this.BackColor = backColor

    abstract member Symbol : char
    default this.Symbol = char shortSymbol
    abstract member Description : string
    default this.Description = ""

    interface IDrawable with
        member this.Position = this.Position
        member this.ShortSymbol = this.ShortSymbol
        member this.ForeColor = this.ForeColor
        member this.BackColor = this.BackColor

        member this.Symbol = this.Symbol
        member this.Description = this.Description

    new(oldBase: DrawableBase, newPosition) = DrawableBase(newPosition, oldBase.ShortSymbol, oldBase.ForeColor, oldBase.BackColor) 

请注意,在极少数情况下,您希望实现接口而不是对类型成员的调用,而是直接作为对字段或私有方法的调用(即复制某些代码并将其作为member this.Position = position内部接口,如类型成员)。这是因为对于类型层次结构,JIT级别的内联虚拟方法和接口并不总是像简单类一样工作,因此调用member this.Position = this.Position会产生额外的虚拟调用开销。但这仅在您需要 nano 优化时才重要,例如将性能从100 Mops增加到150 Mops的简单方法。

答案 1 :(得分:0)

在MSDN上查看F#接口的页面https://msdn.microsoft.com/en-us/library/dd233207.aspx

default永远不会对类中的接口实现有效。

然而,再次来自文档

  

但是,您可以通过包括a来提供默认实现   单独定义成员作为一种方法与   默认关键字