2012-07-27 55 views
5

當我使用「in」契約覆蓋D中的函數時,將檢查繼承的「in」契約。如果它們失敗,則檢查重寫的「in」合同。如果我沒有在合同中指定任何內容,那麼它就會被解釋爲有一個空的「in」合同。所以下面的代碼編譯併成功運行。我該如何有意義地在D接口中使用預條件契約?

module main; 
import std.stdio; 

interface I 
{ 
    void write(int i) 
    in 
    { 
     assert(i > 0); 
    } 
} 

class C : I 
{ 
    void write(int i) 
    { 
     writeln(i); 
    } 
} 

int main() 
{ 
    I i = new C; 

    i.write(-5); 
    getchar(); 

    return 0; 
} 

我只想要I.write()的前提下,當我打電話i.write(),因爲這是靜態已知足以I.write()由編譯器正常運行進行檢查。檢查之後的所有前提條件動態調度由於封裝丟失而從OO角度使我感到奇怪。

我可以在所有實現接口的類中重複前提條件或編寫in { assert(false); },但這很痛苦。這是D語言中的設計錯誤嗎?或者有沒有適當的可擴展的方法來做到這一點?

回答

3

http://dlang.org/dbc.html

如果在派生類中的函數將覆蓋其超類中的函數,那麼只有在函數的合同,它的基礎功能的一個必須得到滿足。重寫函數然後成爲放鬆契約的過程。

沒有合約的函數意味着函數參數的任何值都是允許的。這意味着如果繼承層次結構中的任何函數沒有合同,那麼在覆蓋函數的合同中沒有有用的效果。

相反,所有的外包合同都需要滿足,所以重要的功能就變成了收緊合同的過程。

當多態行爲出現問題時,它實際上是一個困難的設計難題。例如,看看這個bug報告以及相關的長篇討論:http://d.puremagic.com/issues/show_bug.cgi?id=6857

關於如何實現想要的行爲的問題 - 當需要防止複製粘貼時,mixin始終工作,但我不確定是否可以做它來自設計合同範式。不幸的是,需要更多理論上能夠勝任這個問題建議的人。

+0

我不確定該文檔頁是不是隻是過時。我不得不看看TDPL,但有一個類似於OP的問題:http://d.puremagic.com/issues/show_bug.cgi?id=6549 – jpf 2012-07-27 18:34:37

+0

@jpf這是一個增強請求。有些人想要改變這個問題的語言。有關當前行爲的文檔是正確的。 – 2012-07-27 18:38:36

+0

哦,對,我沒有意識到這一點。 – jpf 2012-07-28 12:47:19

0

D中的前提條件是要求函數正確運行。如果你重載了函數,那麼你爲它編寫了一個新的代碼,舊的前提條件 - 這是舊代碼的一個要求 - 不一定是新代碼的要求。

相關問題