区分联合成员方法

Rob*_*Sim 11 inheritance f# discriminated-union

我想定义一个受歧视联盟的所有成员共享的方法.目前我已经像这样实现了它,但它看起来真的很不雅 - 当然还有更好的方法.建议?

type A = 
   {AData:string}
   member this.SharedMethod (x:float) : int= ...
type B =
   {BData:float}
   member this.SharedMethod (x:float) : int= ...
type AB =
| A of A
| B of B

let CallSharedMethod (ab:AB) x =
   match ab with
   | AB.A(a') -> a'.SharedMethod x
   | AB.B(b') -> b'.SharedMethod x
Run Code Online (Sandbox Code Playgroud)

Rod*_*man 18

这样的事情怎么样?

type AB =
    | A of string
    | B of float

    member self.SharedMethod (x : float) =
        match self with
        | A s -> x
        | B f -> f + x
Run Code Online (Sandbox Code Playgroud)

这假设您希望求和类型的每个变量(也称为区分联合)使用float参数执行不同的操作.

对于的情况下A,我只是返回原来的价值,因为(由于没有普遍进行了有益的关系有没有什么我可以做string,并float能产生一个float).


Mar*_*ist 8

在您的示例中,您已经扩充记录类型A,B每个类型都有一个实例成员.但是,您不仅可以扩充记录类型,还可以扩充联合类型(如@Rodrick的答案中所示).如果你这样做,联盟的扩充将由每个DU案例"共享",这就是你所要求的.为了使其更加明确,我重命名了您示例的某些部分:

type A = { AData:string }
type B = { BData:float }

type AB =
    | ACase of A
    | BCase of B
    member __.SharedMethod x = 0

let callSharedMethod (ab:AB) x = ab.SharedMethod x
Run Code Online (Sandbox Code Playgroud)

如果你看一下在对象浏览器(或类似ILSpy反编译)编译代码,你会看到AB被编译为基类两个子类中AB.ACaseAB.BCase,以及SharedMethod属于基类AB.

另请参阅F#3.0规范的第8.5.1节:联合类型中的成员.