摘要:摘要本文章關(guān)注點(diǎn)是理解面向?qū)ο蟾拍睿瑥某橄蟮慕嵌壬先ダ斫鈱ο螅攸c(diǎn)包括理解對象的作用,以及理解面向?qū)ο蟮娜筇卣鞣庋b,繼承,多態(tài)。特性多態(tài)不同對象以自己的方式響應(yīng)相同的消息的能力叫做多態(tài)。
摘要:本文章關(guān)注點(diǎn)是理解面向?qū)ο蟾拍睿瑥某橄蟮慕嵌壬先ダ斫鈱ο螅攸c(diǎn)包括理解對象的作用,以及理解面向?qū)ο蟮娜筇卣鳎ǚ庋b,繼承,多態(tài))。本文重點(diǎn)關(guān)注的是理解概念。
在理解面向?qū)ο笾埃紫然卮饚讉€(gè)問題
1. 什么是對象,類
類,即類型的意思,而每一個(gè)對象都是某類(類型)的具體實(shí)例;比如鳥和魚,都是具體的對象,都是屬于動物這個(gè)類;
對象最簡單的描述就是:對象具有狀態(tài)、行為、和標(biāo)志;
具有狀態(tài)異味著著對象可以擁有內(nèi)部數(shù)據(jù);
行為即方法;
標(biāo)志即對象可以唯一的與其他對象區(qū)分開來,有些類似身份證的作業(yè);
2. 為什么要面向?qū)ο笠约皩ο蟮淖饔?/strong>
在面向?qū)ο螽a(chǎn)生之前,最為熟知的是面向過程的編程,大學(xué)的入門課程C語言就是如此;
“面向過程(結(jié)構(gòu)化編程)是以功能為目標(biāo)導(dǎo)向來設(shè)計(jì)構(gòu)造應(yīng)用系統(tǒng),這種做法導(dǎo)致我們設(shè)計(jì)程序時(shí),不得不將客體所構(gòu)成的現(xiàn)實(shí)世界映射到由功能模塊組成的解空間中,這種轉(zhuǎn)換過程,背離了人們觀察和解決問題的基本思路。
可見結(jié)構(gòu)化設(shè)計(jì)在設(shè)計(jì)系統(tǒng)的時(shí)候,無法解決重用、維護(hù)、擴(kuò)展的問題,而且會導(dǎo)致邏輯過于復(fù)雜,代碼晦澀難懂。于是人們就想,能不能讓計(jì)算機(jī)直接模擬現(xiàn)實(shí)的環(huán)境,用人類解決問題的思路,習(xí)慣,步驟來設(shè)計(jì)相應(yīng)的應(yīng)用程序?這樣的程序,人們在讀它的時(shí)候,會更容易理解,也不需要再把現(xiàn)實(shí)世界和程序世界之間來回做轉(zhuǎn)換。
與此同時(shí),人們發(fā)現(xiàn),在現(xiàn)實(shí)世界中存在的客體是問題域中的主角,所謂客體是指客觀存在的對象實(shí)體和主觀抽象的概念,這種客體具有屬性和行為,而客體是穩(wěn)定的,行為不穩(wěn)定的,同時(shí)客體之間具有各種聯(lián)系,因此面向客體編程,比面向行為編程,系統(tǒng)會更穩(wěn)定,在面對頻繁的需求更改時(shí),改變的往往是行為,而客體一般不需要改變,所以我們就把行為封裝起來,這樣改變時(shí)候只需要改變行為即可,主架構(gòu)則保持了穩(wěn)定。 ”[1]
那抽象出的對象的角色是什么呢?
對象可以理解為模擬中我們概念中的客體,因此對象的存在的目的就是為提供服務(wù),服務(wù)鏈結(jié)構(gòu)可以多樣化。比如汽車為司機(jī)服務(wù),而零件商家為汽車服務(wù)(提供汽車零件)。
"將對象看做是服務(wù)提供者有一個(gè)好處就是有助于提高對象的內(nèi)聚性。"[2]
3. 面向?qū)ο笕筇匦?/strong>
面向?qū)ο蟮娜筇匦缘氖抢斫饷嫦驅(qū)ο蟮年P(guān)鍵點(diǎn)。
特性1: 封裝性
首先要問為什么要封裝以及封裝什么?
封裝的的原因在于:封裝可以讓使用者看不到具體的實(shí)現(xiàn)細(xì)節(jié),創(chuàng)建者可以不用擔(dān)心被使用者誤改,從而減少程序Bug;
而且,允許庫設(shè)計(jì)工作者可以改變程序內(nèi)部結(jié)構(gòu)而不擔(dān)心影響客戶端。創(chuàng)建者改動需要調(diào)用者改動代碼的現(xiàn)象特別是以前很常見的。
同時(shí),客戶端的目標(biāo)也更明確:客戶端程序員不關(guān)心具體的實(shí)現(xiàn),只關(guān)心拿創(chuàng)建者的接口的功能是什么。
封裝的內(nèi)容包括三個(gè)方面:
(1)把自己的數(shù)據(jù)和方法只讓可信的類或者對象操作,即隱藏或者暴漏數(shù)據(jù)、接口。
(2)"找到變化并且把它封裝起來,你就可以在不影響其它部分的情況下修改或擴(kuò)展被封裝的變化部分,這是所有設(shè)計(jì)模式的基礎(chǔ),就是封裝變化,因此封裝的作用,就解決了程序的可擴(kuò)展性"[1]
(3)現(xiàn)實(shí)寫代碼過程中,更多接觸的是:找到重復(fù)度高的,對代碼可重用的部分進(jìn)行封裝;
特性2: 繼承
面向?qū)ο缶幊?OOP)一個(gè)主要功能就是“繼承”。繼承它可以使用現(xiàn)有類的所有功能,并在無需重新編寫原來的類的情況下可以復(fù)用基類的方法或者對這些功能進(jìn)行擴(kuò)展。
在考慮使用繼承時(shí),有一點(diǎn)需要注意,那就是兩個(gè)類之間的關(guān)系應(yīng)該是“屬于”關(guān)系。例如,Cat,Dog,因此這兩個(gè)類都可以繼承 Animal 類。否則,沒有這種關(guān)系的就不要繼承了。
接下來,理解下is-a和is-like-a關(guān)系
對于繼承有這么一個(gè)爭論:繼承應(yīng)當(dāng)只覆蓋基類(并且不添加基類中沒有的新成員函數(shù))嗎?這就意味著派生類與基類是完全相同的類型,因?yàn)樗鼈冇邢嗤慕涌凇=Y(jié)果是,我們可以用派生類的對象代替基類的對象。這被認(rèn)為是純粹替代(pure substitution),常常被稱做替代原則(substitution principle)。在某種意義上,這是對待繼承的理想方法。我們常把基類和派生類之間的關(guān)系看做是一個(gè)“is-a(是)”關(guān)系,因?yàn)槲覀兛梢哉f“圓形是一個(gè)形體”。對繼承的一種測試方法就是看我們是否可以說這些類有“is-a”關(guān)系,而且還有意義。
但是,有時(shí)需要向一個(gè)派生類型添加新的接口元素,這樣就擴(kuò)展了接口。這個(gè)新類型和基類不完全相同了,而且這些新接口元素不能從基類訪問。這可以描述為“is-like-a(像)”關(guān)系;新類型有老類型的接口,但還包含其他函數(shù),所以不能說它們完全相同[3]。
同時(shí),繼承雖然可以復(fù)用基類的方法/屬性,但是很多時(shí)候的濫用導(dǎo)致的問題太多,比如覆蓋基類后,子類默認(rèn)覆蓋相同名字的父類方法。繼承是中非必要的話就不需要覆蓋了,是一定必要的時(shí)候明確指出來,Kotlin語言中繼承基類后,要明確指出覆蓋的方法。
繼承的缺點(diǎn)[4]:
a.破壞封裝,子類與父類之間緊密耦合,子類依賴于父類的實(shí)現(xiàn),子類缺乏獨(dú)立性
b.支持?jǐn)U展,但是往往以增加系統(tǒng)結(jié)構(gòu)的復(fù)雜度為代價(jià)
...
繼承使用原則:
A.繼承樹的層次不可太多,盡量保持在2-3層,首先過多的繼承會導(dǎo)致對象模型的機(jī)構(gòu)太復(fù)雜,難以理解,增加了開發(fā)和設(shè)計(jì)的難度,如果子類和父類之間還有頻繁的方法和屬性覆蓋,更增加了多態(tài)機(jī)制的難度。其次影響系統(tǒng)的可擴(kuò)展性,繼承樹的層次越多在繼承樹上增加一個(gè)新的繼承分支就需要創(chuàng)建更多的類。
B.使用繼承樹上的類時(shí)應(yīng)該盡可能把引用變量聲明為繼承樹的上層類型,首先上層類型定義了下層子類都擁有的屬性和方法并且盡可能為多數(shù)方法提供默認(rèn)實(shí)現(xiàn)從而提高代碼的可重用性。其次上層類型代表一種服務(wù)接口描述系統(tǒng)所能提供的服務(wù),父類不一定實(shí)現(xiàn)這個(gè)服務(wù),提高系統(tǒng)的松耦合及系統(tǒng)本身的可維護(hù)性。
JAVA為什么是單繼承結(jié)構(gòu)?
在單繼承中,所有對象都具有一個(gè)共同的接口,所以他們歸根到底屬于同一基本類型。而多繼承(C++)是無法保證所有對象都屬于同一基本類型。對象的創(chuàng)建和參數(shù)的傳遞相對來說變得簡單,而且使得垃圾回收器的實(shí)現(xiàn)變得容易很多,由于所有對象有其類型的基本信息,因此不會出現(xiàn)無法確認(rèn)對象類型而陷入僵局[5](通俗理解就是我系統(tǒng)運(yùn)行后,不知道哪個(gè)類型的對象在work)。
特性3:多態(tài)
不同對象以自己的方式響應(yīng)相同的消息的能力叫做多態(tài)。多態(tài)性(polymorphisn)允許你將父對象設(shè)置成為和一個(gè)或更多的他的子對象相等的技術(shù),賦值之后,父對象就可以根據(jù)當(dāng)前賦值給它的子對象的特性以不同的方式運(yùn)作。簡單的說,就是一句話:允許將子類類型的指針賦值給父類類型的指針。
與多態(tài)相關(guān)的具體是覆蓋,重載。
覆蓋,是指子類重寫父類的函數(shù)。
重載,是指允許存在多個(gè)同名函數(shù),而這些函數(shù)的參數(shù)表不同(或許參數(shù)個(gè)數(shù)不同,或許參數(shù)類型不同,或許兩者都不同)。
區(qū)分前期綁定和后期綁定
前期綁定,在程序執(zhí)行前根據(jù)編譯時(shí)類型綁定,調(diào)用開銷較小,如C語言只有前期綁定這種方法調(diào)用。
后期綁定,是指在運(yùn)行時(shí)根據(jù)對象的類型進(jìn)行綁定,又叫動態(tài)綁定或運(yùn)行時(shí)綁定。實(shí)現(xiàn)后期綁定,需要某種機(jī)制支持,以便在運(yùn)行時(shí)能判斷對象的類型,調(diào)用開銷比前期綁定大。
Java中的static方法和final方法(private屬于final方法,詳細(xì)的解釋見《Java編程思想》)屬于前期綁定,子類無法重寫final方法,成員變量(包括靜態(tài)及非靜態(tài))也屬于前期綁定。除了static方法和final方法(private屬于final方法)之外的其他方法屬于后期綁定,運(yùn)行時(shí)能判斷對象的類型進(jìn)行綁定[6,7].
4. 對象之間的交流
那么為了能讓對象之間有交互行為,能相互發(fā)送消息和接受消息,該如何做呢?一般來說有兩種方法:1)方法調(diào)用,A對象調(diào)用B對象的方法,這種方法最常用最直接,但是缺點(diǎn)是會導(dǎo)致A依賴于B。這個(gè)問題我們往往會通過面向接口編程在一定程度上消除這種依賴關(guān)系;2)事件消息模式,生產(chǎn)者-消費(fèi)者模式,即采用觸發(fā)事件響應(yīng)事件的模式;通過這種方式,A對象就不是直接調(diào)用B對象的方法了,而是觸發(fā)一個(gè)事件,然后B對象去響應(yīng)這個(gè)事件,或者如果采用消息總線的方式的話,就是A對象通知消息總線發(fā)布某個(gè)事件,然后消息總線發(fā)布這個(gè)事件,然后B對象響應(yīng)這個(gè)事件[8].
參考資料
[1]博客: http://www.cnblogs.com/seesea...
[2]書籍: think in java (4 edition), page 1-4
[3]博客:http://book.51cto.com/art/201...
[4]博客:http://www.cnblogs.com/nuaalf...
[5]書籍: think in java (4 edition), page 11
[6]博客:http://www.cnblogs.com/NotOnl...
[7]博客:http://droidyue.com/blog/2014...
[8]博客:http://www.cnblogs.com/netfoc...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/66041.html
摘要:第一章面向?qū)ο笮“资且婚T完全面向?qū)ο蟮木幊陶Z言嗯什么是面向過程什么又是面向?qū)ο竽卮罄性谖覀冋竭M(jìn)入學(xué)習(xí)這部分前,了解一下面向過程和面向?qū)ο筮@兩個(gè)概念,對于我們接下來的學(xué)習(xí)有很大的好處。這一部分我們會在面向?qū)ο髮W(xué)習(xí)結(jié)束后進(jìn)行系統(tǒng)的整理和總結(jié)。 showImg(https://segmentfault.com/img/remote/1460000019303357); 第一章 面向?qū)ο?小...
摘要:一學(xué)習(xí)資料今天入門了一門新的編程語言,主要對照清華大學(xué)出版社教材語言與面向?qū)ο蟪绦蛟O(shè)計(jì),附帶在上寫了一個(gè)實(shí)例。重要的概念,如對象,屬性,方法等。因此需要在實(shí)操中強(qiáng)化操作技能,加深對概念的鞏固。輔以靈活引用已有的代碼庫,加速以及項(xiàng)目的進(jìn)展。 一、學(xué)習(xí)資料:今天入門了一門新的編程語言,主要對照清華大學(xué)出版社教材《Java 語言與面向?qū)ο蟪绦蛟O(shè)計(jì)》,附帶在eclipse 上寫了一個(gè)實(shí)例。 二...
摘要:首先,需要來理清一些基礎(chǔ)的計(jì)算機(jī)編程概念編程哲學(xué)與設(shè)計(jì)模式計(jì)算機(jī)編程理念源自于對現(xiàn)實(shí)抽象的哲學(xué)思考,面向?qū)ο缶幊淌瞧湟环N思維方式,與它并駕齊驅(qū)的是另外兩種思路過程式和函數(shù)式編程。 JavaScript 中的原型機(jī)制一直以來都被眾多開發(fā)者(包括本人)低估甚至忽視了,這是因?yàn)榻^大多數(shù)人沒有想要深刻理解這個(gè)機(jī)制的內(nèi)涵,以及越來越多的開發(fā)者缺乏計(jì)算機(jī)編程相關(guān)的基礎(chǔ)知識。對于這樣的開發(fā)者來說 J...
摘要:下面我們來使用面向?qū)ο箢悎D這里就不再畫了首先面試題中所提到的我們都可以看成類,比如停車場是一個(gè)類吧,它里面的車位是一個(gè)類吧,攝像頭,屏幕。。。 以下是某場的一道面試題(大概): 1、一個(gè)停車場,車輛入場時(shí),攝像頭記錄下車輛信息2、屏幕上顯示所接收的車輛的信息情況(車牌號)以及各層車位的車位余量3、停車場一共四層車位,其中的三層都為普通車位,還有一層為特殊車位(體現(xiàn)在停車計(jì)費(fèi)價(jià)格上面的不...
閱讀 2879·2021-11-16 11:55
閱讀 2629·2021-09-29 09:34
閱讀 3448·2021-09-01 14:21
閱讀 3783·2019-08-29 12:36
閱讀 708·2019-08-26 10:55
閱讀 4002·2019-08-26 10:20
閱讀 1039·2019-08-23 18:19
閱讀 1206·2019-08-23 17:56