根据文档,您可以使用对象表达式实现多个接口。但是如果你看到下面的代码:
// Define two interfaces
type IFirst =
abstract F : unit -> unit
abstract G : unit -> unit
type ISecond =
abstract H : unit -> unit
abstract J : unit -> unit
// This object expression implements both interfaces.
let implementer : IFirst =
{ new ISecond with
member this.H() = ()
member this.J() = ()
interface IFirst with
member this.F() = ()
member this.G() = () }
Run Code Online (Sandbox Code Playgroud)
所以强制转换IFirst会导致编译器错误。为什么呢?
F#不执行隐式转换。
在let绑定中进行类型注释时,类型必须严格匹配表达式。例如,
let value : obj = new System.Collections.Generic.List<int>()
Run Code Online (Sandbox Code Playgroud)
将无法编译,即使 aList很明显是一个对象。
当你写:
let implementer : IFirst = expr
Run Code Online (Sandbox Code Playgroud)
的类型expr必须绝对是IFirst. 没有像 C# 那样的隐式转换。
对象表达式将其类型作为实现的抽象类型,因此:
{ new ISecond with ... }
Run Code Online (Sandbox Code Playgroud)
将被推断为具有ISecond. 将它与非隐式强制转换规则结合起来,就会出现编译错误。
因为IFirst和ISecond不相关,您可以(运行时)向下转换为IFirst:
let firstImplementer = implementer :?> IFirst
Run Code Online (Sandbox Code Playgroud)
另一种选择是制作一个组合界面:
type IBoth = inherit IFirst inherit ISecond
Run Code Online (Sandbox Code Playgroud)
并做:
let implementer =
{
new IBoth with ...
Run Code Online (Sandbox Code Playgroud)
这样你就可以自由(静态)向上转换为IFirst或ISecond。
let firstImplementer = implementer :> IFirst
let secndImplementer = implementer :> ISecond
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
306 次 |
| 最近记录: |