基于对象和面向对象编程范式辨析和主流编程语言中的应用
生活随笔
收集整理的這篇文章主要介紹了
基于对象和面向对象编程范式辨析和主流编程语言中的应用
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
?
基于對(duì)象和面向?qū)ο缶幊谭妒奖嫖龊椭髁骶幊陶Z(yǔ)言中的應(yīng)用 前言 本文的目的是想告訴大家,為什么C++的模板這么強(qiáng)大。為什么Ruby的Duck Typing(像鴨子那樣編程)這么強(qiáng)大! 基于對(duì)象和面向?qū)ο缶幊谭妒?/font> 關(guān)于基于對(duì)象和面向?qū)ο缶幊谭妒?#xff0c;我有著不同于傳統(tǒng)的理解。我認(rèn)為我的理解更能體現(xiàn)出這2個(gè)范式的本意。 基于對(duì)象,就是使用類封裝操作和操作依賴的數(shù)據(jù)。用類來表示一個(gè)概念。類的公共成員,包括函數(shù)和數(shù)據(jù),就是類的接口,也叫作抽象數(shù)據(jù)類型(ADT)。 面向?qū)ο?#xff0c;就是使用類的接口實(shí)現(xiàn)機(jī)制來表示操作。一個(gè)接口使用一組相關(guān)的公共函數(shù)代表一個(gè)概念的操作。一些類實(shí)現(xiàn)這個(gè)接口。這個(gè)實(shí)現(xiàn)類可以互換。 在使用中,使用接口的指針或者引用來調(diào)用對(duì)象。具體的對(duì)象是接口的某個(gè)實(shí)現(xiàn)類。可以不改變代碼,僅僅改變實(shí)際的對(duì)象來實(shí)現(xiàn)動(dòng)態(tài)修改系統(tǒng)的行為。 這就是“動(dòng)態(tài)多態(tài)”的能力。 面向?qū)ο蟮膭?dòng)態(tài)多態(tài)能力,使抽象能力比函數(shù)更進(jìn)一步。 動(dòng)態(tài)多態(tài),在實(shí)現(xiàn)中是使用了“虛函數(shù)”機(jī)制來實(shí)現(xiàn)的。 對(duì)象指向的本類的虛函數(shù)表來查得真正需要調(diào)用的方法。 語(yǔ)言特性對(duì)比表 C++Java?????? .NET???? Ruby??????????? 類型強(qiáng)類型強(qiáng)類型強(qiáng)類型強(qiáng)類型 靜態(tài)/動(dòng)態(tài)靜態(tài)靜態(tài)檢驗(yàn)類型動(dòng)態(tài)解釋執(zhí)行動(dòng)態(tài) 支持面向過程是否否否 支持基于對(duì)象是否是是 支持范型否是是否 支持模板是否否否 C++通過抽象基類來作為接口,通過對(duì)抽象基類的繼承來實(shí)現(xiàn)這個(gè)接口。 Java和.NET都提供了Interface接口類型。實(shí)現(xiàn)接口的類實(shí)現(xiàn)了這個(gè)機(jī)制。 所以說,C++,Java,.NET都支持面向?qū)ο蟮木幊谭妒健L貏e是java,它只支持面向?qū)ο?#xff08;也就是動(dòng)態(tài)多態(tài))這一種編程范式。其他一概不支持! 動(dòng)態(tài)類型語(yǔ)言,如Ruby,JavaScript都沒有接口。為什么呢? 考慮一下,動(dòng)態(tài)類型語(yǔ)言盡管有類型。但是變量都是沒有類型的。如 //偽代碼 Class Dao1{ Public void save(model){ //保存數(shù)據(jù) } } Class Dao2{ Public void save(model){ //保存數(shù)據(jù) } } Class Service{ @dao; Public void save(model){ this.dao.save(); } } //調(diào)用代碼: New Service(new Dao1).save(model); New Service(new Dao2).save(model); 這里,Dao1,Dao2這2個(gè)類需要實(shí)現(xiàn)一個(gè)共同的接口嗎? 動(dòng)態(tài)類型語(yǔ)言中,盡管對(duì)象是有類型的,但是變量(實(shí)際是指向?qū)ο蟮闹羔?#xff09;是沒有類型的。Service類的變量dao可以是任何類型!只要那個(gè)對(duì)象所屬的類型有Public void save(model);這樣簽名的函數(shù)即可! 動(dòng)態(tài)類型語(yǔ)言中,根本不需要Java等靜態(tài)語(yǔ)言中的接口的概念。這就是動(dòng)態(tài)類型語(yǔ)言著名的Duck Typing“像鴨子一樣編程”的理念。 Java這樣的靜態(tài)類型語(yǔ)言當(dāng)然也有自己的優(yōu)點(diǎn)。那就是通過強(qiáng)制實(shí)現(xiàn)接口??梢员WC程序員不會(huì)因?yàn)楣P誤而調(diào)用錯(cuò)誤的類型。 但是,在實(shí)踐中,動(dòng)態(tài)類型語(yǔ)言的Duck Typing卻是更加靈活,更勝一籌! 動(dòng)態(tài)語(yǔ)言既然沒有接口,那么它們調(diào)用的方法,也就是該類的方法或者繼承的方法,就不需要虛函數(shù)表,也就不是面向?qū)ο蟮摹皠?dòng)態(tài)多態(tài)”機(jī)制了。 Ruby,JavaScript的“多態(tài)”機(jī)制,是“動(dòng)態(tài)基于對(duì)象”的機(jī)制。 根據(jù)我的定義標(biāo)準(zhǔn),Ruby,JavaScript等動(dòng)態(tài)類型語(yǔ)言是“基于對(duì)象”編程范式的語(yǔ)言。是“動(dòng)態(tài)基于對(duì)象”的編程語(yǔ)言。而非面向?qū)ο缶幊陶Z(yǔ)言。 可能你會(huì)說,Ruby,JavaScript 都有“繼承”的能力,怎么能說它們不是面向?qū)ο缶幊陶Z(yǔ)言呢? “繼承”,只是一種代碼重用機(jī)制。和編程范式這樣的設(shè)計(jì)問題根本答不上邊。甚至,我反對(duì)大量使用繼承來重用代碼(少數(shù)特殊情況除外)。我們應(yīng)該使用“組合”來重用代碼。 因?yàn)槔^承會(huì)造成類和類之間的實(shí)現(xiàn)依賴。而組合就不會(huì)有這種依賴關(guān)系。我們只要寫上一些通道代碼就可換取類和類之間的解耦。 好了,現(xiàn)在再讓我們看看C++的基于對(duì)象的編程范式。 C++的基于對(duì)象,就是設(shè)計(jì)一些類,把函數(shù)和函數(shù)需要的數(shù)據(jù)封裝在一個(gè)類中。但是,如何實(shí)現(xiàn)真正的ADT(抽象數(shù)據(jù)類型)呢? 這樣:頭文件代表抽象數(shù)據(jù)類型。實(shí)現(xiàn)文件中提供定義。如果一個(gè)抽象數(shù)據(jù)類型需要多個(gè)實(shí)現(xiàn)呢? 我們?yōu)橐粋€(gè)類提供幾個(gè)實(shí)現(xiàn)文件。用哪一個(gè)就提供哪一個(gè)版本。這樣顯然非常繁瑣。事實(shí)上也沒有人會(huì)這樣編程! 那怎么辦呢?難道C++這樣的靜態(tài)類型語(yǔ)言的“基于對(duì)象”編程范式,注定就不能實(shí)現(xiàn)多態(tài)嗎?C++的模板機(jī)制解決了這個(gè)問題!(在沒有徹底搞懂模板之前,我一直用面向?qū)ο缶幊谭妒绞褂肅++,因此對(duì)C++是怨聲載道!) 如: //偽碼 Template<tyepe?TDao >Class Service{ Private: TDao* dao=new TDao(); Public: Void?save(Model model){ This->dao->save(model); } } //使用 Model*?model=new Model(); Service<Dao>* service=new Service<Dao>(); Service->save(model); 假設(shè)Dao這個(gè)類有Public: Void?save(Model model);這樣簽名的方法。 Void?save(Model model)這個(gè)函數(shù)就是TDao這個(gè)抽象數(shù)據(jù)類型(ADT)公布的方法。 任何類只要有這樣的方法,就滿足TDao這個(gè)ADT,就可以在Service模板類中使用! 對(duì)照上面Ruby的偽碼,我們可以發(fā)現(xiàn): 1,C++的“模板支持的基于對(duì)象”的編程范式,僅僅比動(dòng)態(tài)基于對(duì)象語(yǔ)言多了模板參數(shù)類型的聲明。 而且,C++可以直接在模板類內(nèi)部實(shí)例化類型。真正的類型只有在編譯時(shí)才指定。而動(dòng)態(tài)基于對(duì)象的語(yǔ)言因?yàn)闆]有代表類型的符號(hào),不能實(shí)例化未知的類型。 2,C++的“模板支持的基于對(duì)象”的編程范式,指定了模板參數(shù)類型,也就是在編譯時(shí)需要驗(yàn)證類型。這就比動(dòng)態(tài)基于對(duì)象的語(yǔ)言多了編譯時(shí)靜態(tài)驗(yàn)證類型這一道關(guān)卡,更加安全可靠。 C++中模板之所以偉大,正是因?yàn)樗庆o態(tài)語(yǔ)言中支持基于對(duì)象編程范式的銀彈! C++的“模板支持的基于對(duì)象”的編程范式,令C++擁有了與Ruby等動(dòng)態(tài)基于對(duì)象編程語(yǔ)言的多態(tài)能力相比肩的頂級(jí)語(yǔ)言! 總結(jié) 基于對(duì)象和面向?qū)ο缶幊坦灿腥N范式。它們提供了強(qiáng)大的動(dòng)態(tài)或者靜態(tài)多態(tài)能力,使用它們編程,將令你的程序面向抽象,易于更換。 1,“模板支持的基于對(duì)象”的編程范式。這種編程范式適用于靜態(tài)類型的語(yǔ)言。提供了靜態(tài)多態(tài)的能力。典型的如C++。 模板不同于范型。模板是一種編譯時(shí)的代碼生成機(jī)制。而泛型是對(duì)模板的模擬。在java和.net中都使用類型轉(zhuǎn)換機(jī)制而不是源代碼生成機(jī)制來實(shí)現(xiàn)。 我認(rèn)為模板優(yōu)于范型。.NET的范型實(shí)現(xiàn)的要比Java好。.NET中可以使用new()關(guān)鍵字實(shí)現(xiàn)在范型類中創(chuàng)建未知類型的對(duì)象,而java中不可以。 “模板支持的基于對(duì)象”的編程范式實(shí)現(xiàn)了編譯時(shí)靜態(tài)的多態(tài)。具備了強(qiáng)大的靜態(tài)多態(tài)能力。而且生成的代碼運(yùn)行速度快。 缺點(diǎn)是,如果寫得不好,容易發(fā)生源代碼擴(kuò)張的問題。 2,“靜態(tài)類型語(yǔ)言”的面向?qū)ο蟮木幊谭妒健_@種編程范式適用于靜態(tài)類型的語(yǔ)言。提供了動(dòng)態(tài)多態(tài)的能力。典型的如Java,NET。 使用接口和實(shí)現(xiàn)接口的技術(shù),實(shí)現(xiàn)了動(dòng)態(tài)多態(tài)。并且可以利用靜態(tài)類型檢驗(yàn)的優(yōu)勢(shì),進(jìn)行更加完善的類型安全檢查。 C++也具有進(jìn)行這一編程范式的能力。但是,C++對(duì)于這一編程范式的支持并不是很好。因此,C++編程中,應(yīng)該優(yōu)先使用“模板支持的基于對(duì)象”的編程范式。然后再考慮使用“靜態(tài)類型語(yǔ)言”的面向?qū)ο蟮木幊谭妒綄?shí)現(xiàn)多態(tài)。 3,“動(dòng)態(tài)類型語(yǔ)言”的基于對(duì)象的編程范式。使用Duck Typing“像鴨子一樣編程”的編程理念。這種編程范式適用于動(dòng)態(tài)類型的語(yǔ)言。它們有類型,但是變量不確定類型。典型的如Ruby。這也實(shí)現(xiàn)了動(dòng)態(tài)的多態(tài)能力。總結(jié)
以上是生活随笔為你收集整理的基于对象和面向对象编程范式辨析和主流编程语言中的应用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IT趣闻:世界知名IT公司名字由来
- 下一篇: 手动建立数据库