문제

Suppose I have a pair of obviously contrived C# classes like this:

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

and this:

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); }
}

How do I do this in F#? The obvious code for the properties:

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

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

Triggers an error because the SealedAttribute apparently can't be applied to members. I can, of course, seal the entire class and thereby seal all members, but (and this is a really important but) is that I have a goal of matching an existing class signature exactly and the base class has other virtual/abstract members that should, ideally, remain overridable.

도움이 되었습니까?

해결책

There are currently several limitations to F#'s support for OO, so you should not generally expect to be able to produce an F# class hierarchy which is identical to an arbitrary C# class hierarchy. As far as I know, there is no way to override and seal a virtual method.

다른 팁

Looks like F# defines the Sealed Attribute is defined with its AttributeTargets property set to Class only, its probably not possible to seal members.

This is probably ok, since inheritance and overriding functions is generally less idiomatic in F# than C#. I don't think you can really get what you want without rewriting in more F# idioms. Start with this:

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)

You can say that Baz "overrides" the foo.IsValueLegal member, all other types use the "base" function.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top