【问题标题】:F# partially implemented interface in abstract class抽象类中的 F# 部分实现接口
【发布时间】:2016-02-28 22:48:26
【问题描述】:

我正在尝试编写一个部分实现接口的抽象类。我还想为未实现的值设置默认值。似乎 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)  

这是一个学习项目,所以大部分内容并不重要 - 我可能在这里也做错了一些其他事情 - 请随时批评。

【问题讨论】:

  • 那么这实际上不起作用的是什么?
  • 不喜欢界面下的default关键字。

标签: interface f# abstract-class


【解决方案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# 方式(隐式实现接口)使用类,而不会在需要调用接口成员的每个地方烦人 :&gt;

[<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。

【讨论】:

    【解决方案2】:

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

    default 对于类中的接口实现永远无效。

    但是,再次来自文档

    但是,您也可以通过包含 将成员单独定义为方法以及 默认关键字

    【讨论】:

      猜你喜欢
      • 2012-02-28
      • 2012-07-17
      • 1970-01-01
      • 1970-01-01
      • 2012-01-20
      • 1970-01-01
      • 2014-08-18
      • 2016-11-08
      • 2020-10-20
      相关资源
      最近更新 更多