【问题标题】:Is there a way to have a record inherit an abstract class in F#?有没有办法让记录继承 F# 中的抽象类?
【发布时间】:2014-03-20 06:27:08
【问题描述】:

假设我有一个接口IEvent。这个接口有一个Id 属性,我在 C# 中使用:

public abstract class EventBase : IEvent
{
    public Guid Id { get; protected set; }
]

有没有办法在 F# 记录中继承这个抽象类?

类似:

type OneOfMyEvents = {Id: Guid, Prop: string}
    inherit EventBase(Id)

问题是我想将我的所有事件定义为记录,因为它真的很方便,但我也想强制我的所有事件都具有我不必每次都键入的 Id 属性。

【问题讨论】:

    标签: f#


    【解决方案1】:

    记录不能从类继承,但它们可以实现接口。例如,使用您的IEvent 接口:

    open System
    
    [<Interface>]
    type IEvent =
        abstract Id : Guid with get
    
    
    type MyRecord = {
        Id: Guid;
        Prop: string;
    } with
        interface IEvent with
            member this.Id
                with get () = this.Id
    

    【讨论】:

    • 好吧,这不是我的想法,但它是问题的答案。
    • @TomasJansson 我很困惑,为什么这是答案?您不必在所有记录类型中添加...吗?这如何解决“..有一个我不必每次都输入的 Id 属性”要求?
    • @mahonya,这是答案,因为记录不能从类继承。在我看来,最好的选择就是这里提出的建议。
    • @TomasJansson 谢谢你,我同意。只是我试图了解我是否错过了一个技巧。您必须为每种记录类型编写 IEvent 接口的实现,对吗?这就是我要确认的:)
    • @mahonya,是的,我认为我必须这样做。
    【解决方案2】:

    没有。

    no syntax 用于指定从任何东西继承的记录。

    f# 中的记录类型不同于类类型。从类到记录的继承没有意义:记录具有结构相等语义,而类(通常)具有引用相等语义。因此,继承可能意味着随着继承层次的下降从前者过渡到后者,这违反了我们对 is-a 子类和超类(记录?)之间的关系的期望。

    【讨论】:

      【解决方案3】:

      根据the documentation,记录可以这样定义:

      [ attributes ]
      type [accessibility-modifier] typename = { 
          [ mutable ] label1 : type1;
          [ mutable ] label2 : type2;
          ...
          }
          member-list
      

      虽然您可以向其添加属性和成员,但您不能从基类派生它。


      强制我的所有事件都有一个我不必每次都输入的 Id 属性

      好的,但是,什么更容易输入?

      Id: Guid
      

      inherit EventBase(Id)
      

      在这种情况下,记录语法实际上更简洁。

      【讨论】:

      • 这不是更容易的问题,我想强制我所有的事件都有一个Id。但我完全同意你的观点,即键入第一个更容易,我可能只是通过约定而不是实现接口来强制它。
      猜你喜欢
      • 2013-07-01
      • 1970-01-01
      • 2012-11-24
      • 2021-05-21
      • 2011-01-14
      • 2021-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多