如何在F#中隐藏方法?

时间:2010-03-05 17:14:52

标签: api f#

我目前正在F#中实现一个Spec框架,我希望在我的should类型中隐藏Equals,GetHashCode等方法,这样API就不会被这些混乱。

我知道在C#中,它是通过使类实现这样的接口来完成的:

using System;
using System.ComponentModel;

public interface IFluentInterface
{
    [EditorBrowsable(EditorBrowsableState.Never)]
    bool Equals(object other);

    [EditorBrowsable(EditorBrowsableState.Never)]
    string ToString();

    [EditorBrowsable(EditorBrowsableState.Never)]
    int GetHashCode();

    [EditorBrowsable(EditorBrowsableState.Never)]
    Type GetType();
}

我尝试在F#中做同样的事情:

type IFluentInterface = interface

    [<EditorBrowsable(EditorBrowsableState.Never)>]
    abstract Equals : (obj) -> bool

    [<EditorBrowsable(EditorBrowsableState.Never)>]
    abstract ToString: unit -> string

    [<EditorBrowsable(EditorBrowsableState.Never)>]
    abstract GetHashCode: unit -> int

    [<EditorBrowsable(EditorBrowsableState.Never)>]
    abstract GetType : unit -> Type 
end

在我的类型中实现它:

        interface IFluentInterface with
        member x.Equals(other) = x.Equals(other)
        member x.ToString()    = x.ToString() 
        member x.GetHashCode() = x.GetHashCode()
        member x.GetType()     = x.GetType() 

但没有成功。

我还试图覆盖我的类型中的方法并以这种方式添加属性,但这也没有做到。

所以问题仍然存在,我该如何清理我的API?

修改

感谢帮助(见下文),我能够解决我的问题。

总之,.Equals.GetHashCode可以通过[<NoEquality>] [<NoComparison>]隐藏,但这也会改变语义。

通过EditorBrowsable属性隐藏不起作用。

拥有干净的API并且仍能够重载方法的唯一方法是使这些方法成员保持静态。

通过在我的项目FSharpSpec内浏览,可以找到生成的课程。

可以找到有问题的类型here.

感谢所有帮助我解决这个问题的人。

干杯......

3 个答案:

答案 0 :(得分:5)

重复我的回答

http://cs.hubfs.net/forums/thread/13317.aspx

在F#中你可以禁止等于&amp;通过使用NoEquality和NoComparison属性注释类型来获取GetHashCode(并从intellisense中删除它们),如下所示。用户定义的方法也可以通过Obsolete属性或带有IsHidden = true的CompilerMessage属性从智能感知列表中隐藏。无法从F#intellisense中隐藏System.Object方法GetType和ToString。

[<NoEquality; NoComparison>]
type Foo() =
    member x.Bar() = ()
    member x.Qux() = ()
    [<System.Obsolete>]
    member x.HideMe() = ()
    [<CompilerMessage("A warning message",99999,IsError=false,IsHidden=true)>]
    member x.WarnMe() = ()

let foo = new Foo()
foo.  // see intellisense here

答案 1 :(得分:4)

或者,您可以使用模块中包含的函数使用替代样式设计库。这是在F#中编写功能代码的常用方法,然后您不需要隐藏任何标准的.NET方法。要完成'kvb'给出的示例,以下是面向对象解决方案的示例:

type MyNum(n:int) =
  member x.Add(m) = MyNum(n+m)
  member x.Mul(m) = MyNum(n*m)

let n = new MyNum(1)
n.Add(2).Mul(10) // 'ToString' shows in the IntelliSense

编写代码的功能方式可能如下所示:

type Num = Num of int
module MyNum =
  let create n = Num n
  let add m (Num n) = Num (m + n)
  let mul m (Num n) = Num (m * n)

MyNum.create 1 |> MyNum.add 2 |> MyNum.mul 10

如果您键入MyNum.,F#IntelliSense将显示模块中定义的功能,因此在这种情况下您不会看到任何噪音。

答案 2 :(得分:3)

我认为在F#中一般都没有办法做到这一点。在.Equals.GetHashCode的特定情况下,您可以通过在类型上添加[<NoEquality>]属性使它们无法使用,但除了隐藏这些方法之外,这实际上还具有语义效果。< / p>

修改

也许值得一提的是,F#中很少使用流畅的接口,因为使用组合器和流水线更加惯用。例如,假设我们想要创建一种创建算术表达式的方法。而不是

let x = Expressions.MakeExpr(1).Add(2).Mul(3).Add(4)

我认为大多数F#用户更愿意写

open Expressions
let x = 
  1
  |> makeExpr
  |> add 2
  |> mul 3
  |> add 4

使用这种样式,不需要隐藏成员,因为表达式被传递给组合器,而不是调用表达式构建器的方法。