在改进我的F#的过程中,我一直在尝试类型推断和generics
我经常对在abstract classes和interfaces中为抽象方法准备类型签名所需的工作感到困惑,因为(a)类型签名是一团糟,(b)当我不确切知道类型签名的样子时(我通常从抽象类开始然后派生) .
这是(b)场景的玩具示例,我不喜欢该类来呈现事件( feedAvailable
)并且有两个返回单位的操作( Activate
和 Deactivate
) .
[<AbstractClass>]
type DataSource () =
let mutable isActive = false
let feedAvailable = new Event<_> ()
abstract member Activate: _ -> unit
abstract member Deactivate: _ -> unit
type NotAbstract () =
inherit DataSource ()
override this.Activate (a: int) =
printfn "active: a = %i" a
override this.Deactivate (a: float) =
printfn "Stopped: a = %i" a
type NotAbstractTextual () =
inherit DataSource ()
override this.Activate (a: string, b: int) =
printfn "active: a = %i" a
override this.Deactivate (a: string, b: string) =
printfn "Stopped: a = %i" a
以下代码无法编译 . 是否有一个技巧来推迟抽象类和接口中的函数的类型签名?
一种解决方案可能是使用generics .
[<AbstractClass>]
type DataSource<'a, 'b> () =
let isActive = false
let feedAvailable = new Event<_> ()
abstract member Activate: 'a -> unit
abstract member Deactivate: 'b -> unit
type NotAbstract<'a, 'b> () =
inherit DataSource<'a, 'b> ()
override this.Activate (a) =
printfn "something"
override this.Deactivate (b) =
printfn "something"
type NotAbstractTextual<'a, 'b> () =
inherit DataSource<'a, 'b> ()
override this.Activate (a, b) =
printfn "something else"
override this.Deactivate (a,b,c) =
printfn "something else"
但是,这并没有解决所有问题,f.ex在参数数量上有所不同而没有创建ad-hoc types
并且混淆了泛型签名,如:
type ClassUsingTheDataSource<'a, 'b, 'ds when 'ds :> DataSource<'a,'b>> (dataSource: 'ds) =
2 回答
我很确定你想做什么是不可能的 .
您尝试在DataSource上创建两个成员函数,但是使子类型具体 . 当通用参数不是实际类型的一部分时,您不能这样做 . 这对于F#来说不是问题,你也无法在C#中做到这一点,请参阅下文,了解你可以在C#中做些什么 .
对不起,我不能给你更深入的解释 .
据我所知,
ClassUsingTheDataSource
的构造函数参数没有理由是'ds
的确切类型;它足以成为抽象类型DataSource<'a, 'b>
. 因此你可以像这样写:如果这是您害怕的,您仍然可以在没有显式强制转换的情况下调用此构造函数: