2010-03-05 51 views
5

我目前在F#中實現了一個Spec框架,我想隱藏我的should類型上的Equals,GetHashCode等方法,以便API不會與這些方法混淆。如何隱藏F#中的方法?

我知道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.

謝謝大家誰幫我解決這個問題。

乾杯......

回答

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將顯示模塊中定義的功能,因此在這種情況下不會看到任何噪音。

+0

我會研究一下,我認爲這種方法也會讓我重載這些方法嗎? - 另一方面,我喜歡在F#上進行屏幕演示。 – 2010-03-05 18:09:52

+0

謝謝!不幸的是,使用'let'聲明的函數不能被重載。只有「成員」聲明支持重載。查看有關F#中重載的其他SO問題 - 例如http://stackoverflow.com/questions/2260939/f-overloading-functions – 2010-03-05 18:35:12

+0

那麼在這種情況下,我需要使用一個類型,因爲我非常依賴於重載方法的能力,你可以想象一個should.contain (實際的,預期的)需要針對字符串以不同的順序執行,而不是針對例如序列。 雖然可以重載靜態成員嗎​​?很明顯,如果我將我的Assertion類及其成員設爲靜態,它將不會顯示任何.ToString()...方法。 – 2010-03-05 19:42:45

3

我不認爲有什麼辦法做到這一點在F#一般。在.Equals.GetHashCode的特定情況下,您可以通過在類型上放置[<NoEquality>]屬性使它們不可用,但除了隱藏這些方法之外,實際上它具有語義效果。

編輯

這也可能是值得一提的是一口流利的接口在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 

有了這種風格,也沒有必要隱瞞成員,因爲表達式變得管道輸送到組合程序,而不是調用表達式的方法建設者。

+0

謝謝,我也必須把[我沒有比較]屬性,我做了。在這種情況下,受影響的語義無關緊要。 仍然需要隱藏ToString()和GetType(),但它看起來已經更清潔了。 – 2010-03-05 17:38:27

+1

@「在F#中很少使用流暢的接口」 對不起,該名稱可能會引起誤解,我的唯一目的是隱藏上述方法。 我只是碰巧用這種接口在C#中創建流暢的接口。 – 2010-03-05 17:50:30

5

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

重複我的答案在F#中,你可以禁止Equals已&的GetHashCode(從智能感知刪除)通過註釋與NoEquality類型和屬性NoComparison,如下圖所示。用戶定義的方法也可以通過Obsolete屬性或CompilerMessage屬性通過IsHidden = true從智能感知列表中隱藏。沒有辦法從F#智能感知中隱藏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 
+0

謝謝,布萊恩我應用這個改變來清理它。正如我看到你發現這兩個地方是我問這個問題(我涵蓋了我的基地)。 現在我將考慮托馬斯的方法,因爲他是正確的,我不需要使用類型,模塊會這樣做。 – 2010-03-05 18:17:29