從OO封裝談起

來源:互聯網
上載者:User
在我們熟悉的OO語言中,可以通過private、protected、public等存取控制修飾符將資料和方法分為內部可見、子類可見、外部可見等不同存取層級。本文從一個較為特別的封裝相關例子出發,討論封裝、類型系統、契約式編程相關話題。我們先從例子開始:

public class Person {
    private int _money;

    public void Change(amount){
        this._money += amount;
    }

    public void Exchange(Person p, int amount) {
        p._money -= amount;
        this._money += amount;
    }
}

基於”沒有經過我允許,不許直接動我的錢”的假設,Person類把變數_money作為private成員,並提供public的Change方法。但有爭議的地方在於,在Exchange中我們可以直接存取並修改p._money。請注意上面的代碼在C#編譯器下是完全合法的,類似的代碼在C++和Java下也一樣。我在第一次接觸這個例子的時候,起初有些疑惑編譯器是對還是錯?後來想了一個理由“OO的封裝是基於類的,而非對象”來說服自己。

現在,對這個問題有了更新的認識,希望和大家討論。上面的例子中,我們的理想情況是Person對象本身可以直接存取自己的_money變數,其他Person對象不能直接存取。但OO的封裝實現必須依賴編譯器進行靜態存取權限檢查;既然是靜態那就只能應用到類型,無法應用到對象執行個體。因此,在上例中C#編譯器無法確認p和this是否引用同一對象或不同對象。從這個意義上講,OO的封裝只到類這一層級與其說是設計考慮不如說是不得以的選擇。

從更大的層面上講,這個例子不僅和OO封裝相關,本質上是反映了程式語言類型系統的作用和局限。程式語言的類型系統是一種靜態跟蹤和檢查機制,它能保證程式的類型正確性,但無法保證語義正確性(理想情況下,上面的例子中,p如果和this是同一對象那麼語義正確;否則,語義錯誤)。換句話說,類型正確性可以通過類型系統用形式化的方式進行表達和檢查。那麼語義正確性應該如何來保證呢?有沒有形式化的方式呢?答案也許就像下面這樣:

public class Person {
    private int _money;

    public void Change(amount){
        this._money += amount;
    }

    public void Exchange(Person p, int amount) {
        Assert(this != p);
        p.Change(-amount);
        this._money += amount;
    }
}

增加Assert斷言,就是希望從形式上保證語義的正確性。我的理解是:我們需要一種形式化的方式保證語義的正確性。這是不是就是所謂契約式編程的初衷呢?希望高手指點!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.