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显然无法应用于成员.当然,我可以密封整个类,从而密封所有成员,但是(这是一个非常重要但是)我的目标是完全匹配现有的类签名,而基类具有其他虚拟/抽象成员理想情况下,应该保持可以覆盖.
看起来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
成员,所有其他类型都使用"基础"功能.