Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Interface F#将对象强制转换到接口_Interface_F# - Fatal编程技术网

Interface F#将对象强制转换到接口

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

我有一个名为“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 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]