C#動靜結合編程之四:泛型委派

來源:互聯網
上載者:User
多態

[隨著對OO學習和理解的深入,我已認識到本文關於多態的論述並不準確。最新的認識是:多態是關於類型間代換關係的,文中講的是介面與實現的綁定。]

多態是什嗎?一句話:同一介面和不同實現的綁定。多態讓程式能通過統一的介面(廣義的介面,意指規範)調用不同的實現,從而增強程式的表達能力和靈活性。我們最為熟悉的多態形式是包括介面繼承在內的類型多態:

            var animals = new List<IAnimal>() {
new Cat("Missy"),
new Cat("Mr. Bojangles"),
new Dog("Lassie")
};

foreach (var animal in animals) {
Console.WriteLine(animal.Name + ": " + animal.Talk());
}

有時,我們常常混淆繼承與多態之間的關係,甚至認為二者是同一概念的不同方面。這裡我嘗試理清二者之間的區別與聯絡。在C#中,繼承有兩方面的功能:1.衍生類別複用基類的非私人成員和方法;2.實作類別型多態。功能1的本質是“複用”,即衍生類別通過繼承複用基類代碼,基類與衍生類別之間處於同一抽象層次;功能2的本質是“被複用”,即衍生類別通過繼承以基類/介面的名義被複用,基類與衍生類別是抽象與具體的關係。

我們常常把“基類”(base class)隨意稱作“父類”,不加區別,這在概念上是值得商榷的。“父子關係”是什嗎?兒子繼承父親的某些特徵,強調的是複用,兒子與父親是同一抽象層次的事物,只體現了繼承的複用功能。“動物和狗的關係”顯然不同於“父子關係”,動物與狗是抽象與具體的關係,程式中建立這種關係的主要目的在於以抽象的名義被複用,而非複用基類功能。因此,當繼承的主要目的是複用時,我們可以把同一抽象層次上的基類稱作“父類”,而當繼承的主要目的是實作類別型多態被複用時,“父類”的提法是欠妥的。

正是由於對繼承功能兩個方面欠缺清晰的認識,導致所謂的“濫用繼承”。前文已經談到過,繼承是很強的類型約束,當目的只是為了複用時,如果採用繼承的方式,往往會帶來一些副作用,比如:在C#中,對象在其生命週期內無法改變繼承關係,兒子像老子就必須像一輩子。其實複用並非OO的專利,在幾乎所有場合,我們都可以通過其他方式實現複用,比如組合方式。因此,這裡給出一條避免濫用繼承的明確建議:當目的是複用,請考慮採用組合,而非繼承!

泛型委派

多態與繼承沒有必然的聯絡,繼承只是實作類別型多態的一種手段。我理解,凡是符合介面與實現的綁定都屬於多態。那麼C#中的委託是不是多態呢?當然是,我姑且稱它為方法多態,委託的調用者通過統一的委託調用不同的方法實現。與繼承多態相比,委託消除了類型約束,凡是符合簽名的方法都可以被委託調用,因此更加靈活。還有,泛型是不是多態呢?也是。泛型類/方法的編寫者,通過使用統一的型別參數T表達程式的行為,把T具體化的工作交給泛型類/方法的使用者。

委託是多態,泛型是多態,那麼泛型委派是不是多態呢?當然更是,而其是非常強大的多態!其強大就在於融合了泛型和委託的抽象能力,又不失靜態類型的安全性。GoF早就曾意識到泛型與委託相結合將是多麼強大的抽象能力啊!而有幸的是,C#早已在語言層面直接支援泛型委派(據我所知,C++ boost庫也提供了類似泛型委派的泛型函數指標)。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.