我还没有听说过部分接口实现,尽管我已经在 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。