谈谈java面向对象思想_对于Java面向对象思想的理解
在Java中,除了8種基本數(shù)據(jù)類型。其他皆為對(duì)象!
面向?qū)ο笾饕?/p>
三個(gè)基本特征:封裝,繼承,多態(tài)。
封裝
主要概念是指:隱藏對(duì)象的屬性和實(shí)現(xiàn)細(xì)節(jié),僅對(duì)外暴露公共的訪問(wèn)方式。封裝是面向?qū)ο笞罨镜奶卣髦?#xff0c;是類和對(duì)象概念的主要特性。
良好的封裝所具有的優(yōu)點(diǎn):
1,隱藏信息和細(xì)節(jié),提高安全性
2,良好的封裝可以減少耦合性,提高復(fù)用性
3,對(duì)類內(nèi)部結(jié)構(gòu)可以隨意修改,只要保證公有接口始終返回正確的結(jié)果即可。
在Java中的體現(xiàn):
public default protected private等設(shè)置訪問(wèn)權(quán)限的關(guān)鍵字
例如,類的屬性私有化private修飾,提供公有的setter getter方法對(duì)值進(jìn)行獲取和修改。
同時(shí),還可以在setter getter函數(shù)里進(jìn)行數(shù)據(jù)校驗(yàn)和對(duì)返回值做限制。這就是提高安全性的體現(xiàn)。
繼承
繼承是一種聯(lián)結(jié)類的層次模型,Java允許并且鼓勵(lì)代碼的重用,繼承提供了一種明確表示共性的方法,來(lái)使代碼可以進(jìn)行復(fù)用。
繼承的出現(xiàn),讓類與類之間產(chǎn)生了關(guān)聯(lián),提供了多態(tài)的前提條件。
講到繼承,就要提到三個(gè)東西:構(gòu)造器,protected關(guān)鍵字,向上轉(zhuǎn)型:
1,構(gòu)造器:我們已經(jīng)知道,父類中private修飾的屬性和方法子類是無(wú)法繼承的,而還有一個(gè)無(wú)法繼承的就是構(gòu)造器。構(gòu)造器只能調(diào)用而不能被繼承。
類在實(shí)例化的時(shí)候會(huì)調(diào)用自身構(gòu)造器,而java編譯器會(huì)默認(rèn)在子類構(gòu)造器的第一行用super()先調(diào)用父類的無(wú)參構(gòu)造器。如果父類沒(méi)有無(wú)參構(gòu)造器,則子類在實(shí)例化的時(shí)候會(huì)報(bào)錯(cuò)。這個(gè)時(shí)候就需要顯示的在子類構(gòu)造器第一行(必須在第一行)指定構(gòu)造器super(args)來(lái)指定調(diào)用父類哪個(gè)構(gòu)造器。
2,protected關(guān)鍵字:proctected關(guān)鍵字修飾的屬性和方法,可以隔絕外部其他類的訪問(wèn),卻可以讓子類有權(quán)限訪問(wèn)。
但是最好還是把屬性都以private修飾,父類中希望子類可以訪問(wèn)到,又不希望公有的方法,可以用protected修飾
3,向上轉(zhuǎn)型:最典型的還是List list = new ArrayList()將子類的實(shí)例聲明為父類的類型,提高了通用性,也隱藏了子類的具體實(shí)現(xiàn)。因?yàn)檫@是一個(gè)由專用向通用的轉(zhuǎn)換,所以總是安全的。唯一缺陷就是專有屬性和方法的丟失。
但是繼承同時(shí)又存在缺陷:
1),繼承是一種強(qiáng)耦合關(guān)系,子類會(huì)由于父類的改變而改變
2),繼承破壞了封裝的特性,對(duì)于父類而言,它的實(shí)現(xiàn)和細(xì)節(jié)對(duì)于子類來(lái)說(shuō)都是透明的
所以到底要不要繼承:《Thinking in java》提供了一個(gè)解決方案:問(wèn)一問(wèn)自己是否需要從子類向父類進(jìn)行向上轉(zhuǎn)型。如果必須向上轉(zhuǎn)型,則繼承是必要的,但是如果不需要,則應(yīng)當(dāng)好好考慮自己是否需要繼承
使用繼承的時(shí)候,一定要注意,兩個(gè)類之間是從屬關(guān)系,父子關(guān)系的。子類應(yīng)該是基于父類原有的特性,派生出來(lái),并在無(wú)需編父類代碼的情況下,提供擴(kuò)展的功能和方法。
不要為了使用某個(gè)類的其中一個(gè)特性,而去繼承該類!!!!
多態(tài)
多態(tài),指的就是:
程序中定義的引用變量所指向的具體類型,和通過(guò)該引用變量發(fā)出的方法調(diào)用,在編程期間并不確定,而是在程序運(yùn)行期間才確定。
1、如何理解多態(tài):
因?yàn)樵诔绦蜻\(yùn)行時(shí)才確定到具體的類,所以不用修改源碼,就能讓引用變量綁定到不同的類型實(shí)現(xiàn)上,從而導(dǎo)致引用調(diào)用的方法發(fā)生改變,即不修改具體代碼,就可以讓程序在運(yùn)行時(shí)改變綁定的具體代碼,表現(xiàn)不同的運(yùn)行狀態(tài)。這就是多態(tài)性。
2、多態(tài)的好處:
多態(tài)允許不同類對(duì)象,對(duì)同一個(gè)消息作出響應(yīng)。即同一個(gè)消息可以根據(jù)發(fā)送對(duì)象的不同而采用不同的行為方式(發(fā)送消息就是函數(shù)調(diào)用)。
主要好處如下:
1)可替換性。多態(tài)對(duì)已存在的代碼具有可替換性。
2)可擴(kuò)充性。新增加的子類不影響已經(jīng)存在的類結(jié)構(gòu)。
3)接口性。多態(tài)是父類通過(guò)方法簽名,向子類提供一個(gè)公共接口,由子類來(lái)完善或者重寫(xiě)它來(lái)實(shí)現(xiàn)的。
4)靈活性。
5)簡(jiǎn)化性。
3、Java中多態(tài)的體現(xiàn):
重寫(xiě)(覆蓋)
動(dòng)態(tài)鏈接(動(dòng)態(tài)調(diào)用)
重載
4、多態(tài)的三個(gè)必要條件:
繼承
重寫(xiě)
向上轉(zhuǎn)型。
5、多態(tài)的作用:
我們知道,封裝可以隱藏細(xì)節(jié),使得代碼模塊化,繼承可以擴(kuò)展已存在的模塊化代碼(父類),實(shí)現(xiàn)代碼的復(fù)用。
而多態(tài),則是實(shí)現(xiàn)了接口的復(fù)用,多態(tài)的作用,就是在類的實(shí)現(xiàn)和派生的時(shí)候,保證使用基類下面,任意一個(gè)子類實(shí)例的屬性和方法,都可以正確調(diào)用。
6、虛擬機(jī)如何實(shí)現(xiàn)多態(tài):
在JVM中,是使用了動(dòng)態(tài)綁定技術(shù)(dynamic binding),執(zhí)行期間判斷所引用對(duì)象的實(shí)際類型,根據(jù)實(shí)際類型調(diào)用對(duì)應(yīng)的方法.
重載嚴(yán)格意義上并不屬于多態(tài),重載的具體實(shí)現(xiàn)是:編譯器根據(jù)不同的參數(shù)表,對(duì)同名函數(shù)的名稱做修飾,然后這些同名函數(shù)就變成了不同的函數(shù)。對(duì)重載函數(shù)的調(diào)用,在編譯期間就已經(jīng)確定了,是靜態(tài)的(注意!是靜態(tài)的),因此,重載和多態(tài)無(wú)關(guān)。
真正和多態(tài)相關(guān)的是重寫(xiě),當(dāng)子類重寫(xiě)了父類中的函數(shù)后,父類的 指針,根據(jù)賦值給它不同的子類對(duì)象指針,動(dòng)態(tài)的調(diào)用屬于子類的該函數(shù),這樣在編譯期間是無(wú)法確定的,只有在運(yùn)行期間,才會(huì)把動(dòng)態(tài)鏈接轉(zhuǎn)變?yōu)橹苯右?稱為動(dòng)態(tài)鏈接,詳見(jiàn)JVM內(nèi)存模型-棧幀)
五個(gè)基本原則
1、單一職責(zé)原則(Single-Resposibility Principle? SRP)
對(duì)一個(gè)而言,應(yīng)該僅有一個(gè)引起它變化的原因
本原則是我們非常熟悉的"高內(nèi)聚原則"的引申。同時(shí),本原則還揭示了內(nèi)聚性和耦合性:如果一個(gè)類承擔(dān)的職責(zé)過(guò)多,那么這些職責(zé)就會(huì)相互依賴,一個(gè)職責(zé)的變化可能會(huì)影響另一個(gè)職責(zé)的履行。其實(shí)OOP的實(shí)質(zhì),就是合理進(jìn)行類的職責(zé)分配
2、開(kāi)—閉原則(Open-Closed principle? OCP)
軟件應(yīng)該是可以擴(kuò)展的,但是不可以修改
也就是對(duì)擴(kuò)展開(kāi)放,對(duì)修改封閉。當(dāng)變化來(lái)臨時(shí),不需要(或者不允許)修改原來(lái)的代碼,只需要在原有的基礎(chǔ)上擴(kuò)展(同時(shí)原有的代碼也要求支持?jǐn)U展),那么這個(gè)軟件設(shè)計(jì)就是滿足開(kāi)閉原則的。
此原則在Java中最典型的體現(xiàn)就是:抽象類抽象基類和接口。通過(guò)抽象類,把一些不可變的操作封裝起來(lái),而提供抽象接口供子類實(shí)現(xiàn),來(lái)實(shí)現(xiàn)各自變化的需求。
這個(gè)原則應(yīng)用在類的設(shè)計(jì)中,要滿足該原則就要充分的考慮到接口封裝,抽象機(jī)制和多態(tài)。
3、里氏替換原則(Liskov-Substituion Principle? LSP)
子類型必須能夠替換掉它們的基類型
本原則和開(kāi)閉原則關(guān)系密切,正是基于子類的可替換性,才使得基類可以無(wú)需修改,只要子類繼承就可以實(shí)現(xiàn)擴(kuò)展特性。這是保證繼承復(fù)用的基礎(chǔ)
在Java中的典型體現(xiàn)就是 基于接口的框架設(shè)計(jì),例如JDBC,集合類。
JDBC只提供了基本的接口,返回的對(duì)象類型也是接口,這樣就在選擇返回對(duì)象的時(shí)候,有了更大的靈活性:只要是繼承了返回接口類型的子類實(shí)例,都可以作為結(jié)果返回。而服務(wù)提供者無(wú)需暴露子類的實(shí)現(xiàn),調(diào)用者也無(wú)需關(guān)心子類的實(shí)現(xiàn)。而提供者在對(duì)實(shí)現(xiàn)進(jìn)行優(yōu)化升級(jí)時(shí),對(duì)調(diào)用者也是不可見(jiàn),同時(shí)也沒(méi)有影響的。
集合類提供了一些基本集合的接口,例如 List Map Set。我們可以在聲明時(shí)用這些接口類型作為聲明對(duì)象,無(wú)需關(guān)心具體的實(shí)現(xiàn)類型是如何操作的,集合框架可以很好的把實(shí)現(xiàn)類型和代碼隱藏起來(lái),對(duì)調(diào)用者透明。例如List可以用來(lái)接收ArrayList,也可以用來(lái)接收LinkedList。可以用來(lái)接收任何實(shí)現(xiàn)了List接口的類的實(shí)例。
以上兩點(diǎn),充分的利用了里氏替換原則的特性,實(shí)現(xiàn)了封裝的基本特征。
4、接口隔離原則(Interface-Segregation Principle ISP)
多個(gè)專用接口優(yōu)于一個(gè)單一的通用接口
本原則是單一職責(zé)原則用于接口設(shè)計(jì)的自然結(jié)果。基本思想就是,不要讓客戶端依賴他們不需要的接口。
一個(gè)接口應(yīng)該保證,實(shí)現(xiàn)該接口的實(shí)例對(duì)象可以只呈現(xiàn)一個(gè)單一的角色。這樣當(dāng)接口發(fā)生改變時(shí),對(duì)其他客戶端造成的影響會(huì)更小。
把多個(gè)不同職責(zé)的功能分到不同的接口中去,提高代碼的靈活性和穩(wěn)定性,降低耦合性。
5、依賴倒置原則(Dependecy-Inversion Principle DIP)
抽象不應(yīng)該依賴于細(xì)節(jié),細(xì)節(jié)應(yīng)該依賴于抽象
具體來(lái)說(shuō)就是,軟件設(shè)計(jì)中,高層不依賴于低層,兩者都依賴于抽象。抽象應(yīng)該依賴于抽象,而不依賴于具體實(shí)現(xiàn)細(xì)節(jié)。即:對(duì)接口編程
在Java中的體現(xiàn)還是,接口和抽象類
拿最簡(jiǎn)單的Spring IOC來(lái)說(shuō),當(dāng)我們注入的時(shí)候,接收參數(shù)類型應(yīng)該是接口,而注入的對(duì)象,可以是實(shí)現(xiàn)了接口的各種子類,當(dāng)我們想改變接口表現(xiàn)的特性的時(shí)候,無(wú)需修改代碼,只要修改注入的實(shí)現(xiàn)類對(duì)象就可以。
RPC框架(例如Dubbo)開(kāi)放的接口也同樣基于這個(gè)原則。
上面說(shuō)的JDBC,集合類框架 都基于這個(gè)原則來(lái)提供實(shí)現(xiàn)。提供接口對(duì)象,而把實(shí)現(xiàn)類隱藏在內(nèi)部。
總結(jié)
以上是生活随笔為你收集整理的谈谈java面向对象思想_对于Java面向对象思想的理解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: php面向对象异常处理,PHP 错误和异
- 下一篇: php 自定义条件,php – 使用两个