如何封锁被覆盖的财产

pli*_*nth 9 .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;
    }
}
Run Code Online (Sandbox Code Playgroud)

还有这个:

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); }
}
Run Code Online (Sandbox Code Playgroud)

我怎么在F#中这样做?属性的明显代码:

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

[<Sealed>]
override this.IsValueLegal value = // ...
Run Code Online (Sandbox Code Playgroud)

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

Jul*_*iet 5

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

这可能是正常的,因为继承和压倒一切的功能一般是在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)
Run Code Online (Sandbox Code Playgroud)

你可以说Baz"覆盖" foo.IsValueLegal成员,所有其他类型都使用"基础"功能.


kvb*_*kvb 3

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