如何封锁被覆盖的财产

时间:2010-12-02 20:44:42

标签: .net inheritance f# c#-to-f#

假设我有一对明显设计的C#类:

public abstract class Foo {
    public abstract int[] LegalValues { get; }
    public virtual bool IsValueLegal(int val) {
        return Array.IndexOf(LegalValues, val) >= 0;
    }
}

和此:

public class Bar : Foo {
    static int[] _legalValues = new int[] { 0, 1 }; // whatever
    public sealed override int[] LegalValues 
        { get { return _legalValues; } }
    public sealed override bool IsValueLegal(int val)
        { return base.IsValueLegal(val); }
}

我如何在F#中执行此操作?属性的明显代码:

[<Sealed>]
override this.LegalValues with get() = // ...

[<Sealed>]
override this.IsValueLegal value = // ...

触发错误,因为SealedAttribute显然无法应用于成员。 当然,我可以密封整个班级,从而密封所有成员,但是(这是非常重要但是)我的目标是匹配现有的班级签名完全< / strong>并且基类具有其他虚拟/抽象成员,理想情况下应该保持可覆盖。

2 个答案:

答案 0 :(得分:5)

看起来F#定义了Sealed Attribute的定义,其AttributeTargets属性设置为Class,它可能无法密封成员。

这可能是 ok ,因为继承和覆盖函数在F#中通常不如C#惯用。我不认为你可以真正得到你想要的东西而不用更多的F#成语重写。从这开始:

type foo =
    | Bar
    | Baz
    | Qux
        with
            member this.LegalValues =
                match this with
                | Bar -> [0; 1]
                | Qux -> [-1; 0; 1]
                | Baz -> [0 .. 10 ]
            member this.IsValueLegal value =
                match this with
                | Baz -> value >= 0 && value <= 10
                | _ -> List.exists (fun x -> x = value) (this.LegalValues)

您可以说Baz“覆盖”foo.IsValueLegal成员,所有其他类型都使用“基本”功能。

答案 1 :(得分:3)

目前F#支持OO存在一些限制,因此通常不应期望能够生成与任意C#类层次结构相同的F#类层次结构。据我所知,没有办法覆盖和密封虚拟方法。