Interface F#将对象强制转换到接口
我有一个名为“Pane”(think glass Pane)的类,它实现了IPane:Interface F#将对象强制转换到接口,interface,f#,Interface,F#,我有一个名为“Pane”(think glass Pane)的类,它实现了IPane: type IPane = abstract PaneNumber : int with get, set abstract Thickness : float<m> with get, set abstract ComponentNumber : int with get, set abstract Spectra : IGlassDataValues with g
type IPane =
abstract PaneNumber : int with get, set
abstract Thickness : float<m> with get, set
abstract ComponentNumber : int with get, set
abstract Spectra : IGlassDataValues with get, set
...
type Pane(paneNumber, componentNumber, spectra, ...) =
let mutable p = paneNumber
let mutable n = componentNumber
let mutable s = spectra
...
interface IPane with
member this.PaneNumber
with get() = p
and set(value) = p <- value
member this.ComponentNumber
with get() = n
and set(value) = n <- value
member this.Spectra
with get() = s
and set(value) = s <- value
...
但是,我需要将其强制转换为IPane列表,因为这是另一个函数中的参数类型。以下代码产生错误:
let p = [ p1; p2 ] :> IPane list
'Type constraint mismatch. The type
Pane list
is not compatible with type
IPane list
The type 'IPane' does not match the type 'Pane'
这让人困惑,因为窗格实现了IPane。简单地将窗格列表对象作为参数传递到所需函数中也会产生错误
如何将窗格列表转换为IPane列表?F#不允许以您想要的方式进行继承
更好的方法是使用:
[p1 ;p2] |> List.map (fun x -> x:> IPane)
或者,您可以更改您的函数以使用如下内容
let f (t:#IPane list) = ()
在这里,您可以执行
f[p1;p2]
,因为
告诉编译器,从IPane
继承的任何类型都是可以的。解决方案比我想象的要简单
我将p1和p2定义为:
let p1 = new Pane(1, 2, blah, blah)
let p2 = new Pane(2, 2, blah, blah)
但是,如果我在此时将它们转换为iPane,一切都会正常工作:
let p1 = new Pane(1, 2, blah, blah) :> IPane
let p2 = new Pane(2, 2, blah, blah) :> IPane
上面John Palmer的解决方案可能更严格,因为原始窗格对象被维护为具体类型。另一种方法是:
let p = [p1; p2] : IPane list
// or equivalently
let p : IPane list = [p1; p2]
在您的原始代码中,首先它在没有任何约束的情况下推断出[p1;p2]
的类型,它发现该类型是窗格列表
,然后它尝试将其上溯到IPane列表
,但它无法这样做,因为F有严格的变化规则:即使窗格
是IPane
的子类型,窗格列表
不是IPane列表
的子类型
另一方面,在我上面的代码中,它不是试图推断
[p1;p2]
的类型,而是验证它是否可以匹配给定的类型IPane列表
;在这样做的过程中,它隐式地将单个列表元素p1
和p2
向上投射到IPane
对于未来的问题,这里几乎所有的代码都是无关的,一个简单的复制是typet()=class end;类型q()=继承t();设f(a:t列表)=();f[q();q()]
谢谢,说实话,有时候我觉得了解一下用户的意图很有用,但我会接受你的观点。
let p = [p1; p2] : IPane list
// or equivalently
let p : IPane list = [p1; p2]