2011-06-06 62 views

回答

4

您可能想要換出類似於單元測試的實現

+0

你是說我在哪裏有類Foo的東西:公共基地和類FooTest:公共基地,我會實例化FooTest在單元測試程序,可能具有樁功能? – Ternary 2011-06-06 17:58:06

+0

是的,或者使用像googlemock這樣的模擬框架來爲你做 – Rich 2011-06-06 18:01:31

+0

你可以通過擴展使用的類(這也意味着你可以重用已經存在的功能)而無需特殊的接口。 – Voo 2011-06-06 18:12:32

3

您爲什麼要這樣做的一個原因是可測試性。當依賴對象被定義爲接口時,測試依賴對象就簡單多了。這給了容易模擬或存根的能力。

+0

過去,除非考慮IOC和依賴注入,否則我想不出一個好的理由。這個類可能會在稍後改變它的實現,而不會改變簽名嗎? – hivie7510 2011-06-06 17:51:33

+1

也許這只是我,但是擴展類本身並添加一些方法(或構造函數)爲測試設置私有變量通常更容易(而且更少錯誤)?或者,如果我想添加日誌記錄,我可以輕鬆地覆蓋這些方法,處理日誌記錄並調用超類。沒有這個,你必須兩次實現通用功能,這聽起來像是一個壞主意。 – Voo 2011-06-06 17:53:09

+0

我通常在.NET中工作,所以我更喜歡設置我的嘲笑的期望,然後重播行爲。在C++中,這可能完全不同。 – hivie7510 2011-06-06 17:55:18

1

如果你可以100%確定總是隻有一個派生類和一個派生類?沒有多少理由。但是:事實上,你幾乎不會100%確定任何東西,當然也不會代碼的未來。

+0

如果你遇到那個不確定的未來點,你必須再次實現它,你也不能確定你提出的抽象是正確的。 – jason 2011-06-06 17:52:21

+0

@Jason當然,你可能會發現你的界面本身存在嚴重問題。所以,當你沒有擺脫所有問題時,至少你會擺脫一個問題。只是爲了增加Jason提出的問題的一個例子:如果你環顧了許多成熟的框架,你會發現像這樣的名字的接口,這些名稱正是在這種情況下創建的(可怕的柺杖,但仍然比你要做的更好如果你曾經使用過課程,那就去做!)。 – Voo 2011-06-06 18:09:15

2

違反reused abstraction principle

總之,不要這樣做。

那些誰說「測試」俯瞰,你可以只更換

Base < - > Derived 
Base < - > DerivedForMockingAndTesting 

Derived < - > DerivedForMockingAndTesting  

也就是說,讓你現有的實現Derived作爲「抽象」被嘲笑並在單元測試中進行測試。

+0

如果Derived'的構造函數做了一些你不想讓模擬操作的東西? – 2011-06-06 18:09:36

+0

還是有非虛擬功能? – Puppy 2011-06-06 19:57:22

1

您可能會發現該類的不同版本需要二進制兼容。你也可能會發現,由於其他原因,你希望封裝類的定義 - 例如,因爲定義需要一個包含可憐的宏的頭,那種事情,或包含定義類所需的頭的頭編譯時間很長。

例如,我寫了一個類來封裝我的操作系統提供的功能 - 目前,像動態加載和創建窗口這樣的功能。即使只有一個編譯目標(Windows等)的實現,我選擇使用運行時抽象,因爲我想保證我的代碼的其餘部分從未看到特定於平臺的頭文件,並且Windows頭部充滿了如此多的宏和東西,我不希望它們泄漏出去。

1

最明顯的原因是能夠將類' 實現放在源文件中,而不是放在標題中。在頭文件中公開的所有 是抽象基類(以及構造它的必要工廠函數 ,但這可能是一個靜態成員)。這個 避免了必須包含任何成員數據的頭文件; pimpl 成語在C++中更習慣於此,但使用抽象類如 這遠不是未知數,並且工作得很好。