如何在不限于一个文件的情况下在 F# 中实现访问者模式?
How to implement a visitor pattern in F# while not being restricted to one file?
以下代码示例演示了 F# 中访问者模式的实现
module VisitorPattern
type IVisitor =
abstract Visit : ObjectA -> unit
abstract Visit : ObjectB -> unit
and IVisitable =
abstract InvokeVisit : IVisitor -> unit
and ObjectA =
interface IVisitable with
member this.InvokeVisit (visitor: IVisitor) =
visitor.Visit(this)
and ObjectB =
interface IVisitable with
member this.InvokeVisit (visitor: IVisitor) =
visitor.Visit(this)
type MyVisitor =
member this.Visit (a : ObjectA) =
printfn "Visited object A"
member this.Visit (b : ObjectB) =
printfn "Visited object B"
这编译得很好,但由于使用了 and
关键字,我们只能在一个文件中实现所有类型 IVisitable
。这个关键字似乎是允许相互类型引用所必需的。
有没有一种方法可以让我们不局限于一个文件来实现这个模式?
(我不是征求您是否应该在 F# 中使用此模式的意见)
编辑:我问这个问题是因为访问者模式在与 C# 代码进行互操作时是相关的。
模式匹配应该可以用一小部分复杂性和开销实现相同的目标。以我个人的经验,这是在 F# 中实现访问者模式的最佳方式。
type Visitor = A of int | B of int
match a with
| A x -> 1 * x
| B x -> 2 * x
然后对于一些可能的 C#
private static void Main()
{
Visitor a = Visitor.A(7)
switch(a){
case Visitor.A x:
x.Item * 1;
break;
case Visitor.B x:
x.Item * 2;
break;
default:
throw new ArgumentOutOfRangeException();
}
}
如果您确实需要为 C# 互操作使用 OO 模式,我认为解耦类型的最佳方法是使用泛型:
module VisitorPattern =
type IVisitor<'T> =
abstract Visit : 'T -> unit
type IVisitable<'T> =
abstract InvokeVisit : IVisitor<'T> -> unit
module Visitors =
open VisitorPattern
type ObjectA () =
interface IVisitable<ObjectA> with
member this.InvokeVisit (visitor : IVisitor<ObjectA>) =
visitor.Visit this
type ObjectB () =
interface IVisitable<ObjectB> with
member this.InvokeVisit (visitor : IVisitor<ObjectB>) =
visitor.Visit this
以下代码示例演示了 F# 中访问者模式的实现
module VisitorPattern
type IVisitor =
abstract Visit : ObjectA -> unit
abstract Visit : ObjectB -> unit
and IVisitable =
abstract InvokeVisit : IVisitor -> unit
and ObjectA =
interface IVisitable with
member this.InvokeVisit (visitor: IVisitor) =
visitor.Visit(this)
and ObjectB =
interface IVisitable with
member this.InvokeVisit (visitor: IVisitor) =
visitor.Visit(this)
type MyVisitor =
member this.Visit (a : ObjectA) =
printfn "Visited object A"
member this.Visit (b : ObjectB) =
printfn "Visited object B"
这编译得很好,但由于使用了 and
关键字,我们只能在一个文件中实现所有类型 IVisitable
。这个关键字似乎是允许相互类型引用所必需的。
有没有一种方法可以让我们不局限于一个文件来实现这个模式?
(我不是征求您是否应该在 F# 中使用此模式的意见)
编辑:我问这个问题是因为访问者模式在与 C# 代码进行互操作时是相关的。
模式匹配应该可以用一小部分复杂性和开销实现相同的目标。以我个人的经验,这是在 F# 中实现访问者模式的最佳方式。
type Visitor = A of int | B of int
match a with
| A x -> 1 * x
| B x -> 2 * x
然后对于一些可能的 C#
private static void Main()
{
Visitor a = Visitor.A(7)
switch(a){
case Visitor.A x:
x.Item * 1;
break;
case Visitor.B x:
x.Item * 2;
break;
default:
throw new ArgumentOutOfRangeException();
}
}
如果您确实需要为 C# 互操作使用 OO 模式,我认为解耦类型的最佳方法是使用泛型:
module VisitorPattern =
type IVisitor<'T> =
abstract Visit : 'T -> unit
type IVisitable<'T> =
abstract InvokeVisit : IVisitor<'T> -> unit
module Visitors =
open VisitorPattern
type ObjectA () =
interface IVisitable<ObjectA> with
member this.InvokeVisit (visitor : IVisitor<ObjectA>) =
visitor.Visit this
type ObjectB () =
interface IVisitable<ObjectB> with
member this.InvokeVisit (visitor : IVisitor<ObjectB>) =
visitor.Visit this