目前的工作對我非常重要嚼酝。
我是一Android(以前做C開發(fā))開發(fā)工程師,但是目前部門沒有Android項目了竟坛,所以要轉(zhuǎn)java闽巩。在慕課網(wǎng)購買的職業(yè)路徑之java钧舌。已經(jīng)學習完java多態(tài),總結(jié)一下涎跨。
1 面向?qū)ο笳Z音 java - 封裝 繼承 多態(tài)延刘。
封裝 - 在一個class類中設(shè)置變量和方法 - - 通過構(gòu)造方法初始化 - 對外拋出方法調(diào)用
封裝從字面上來理解就是包裝的意思,專業(yè)點就是信息隱藏六敬,是指利用抽象數(shù)據(jù)類型將數(shù)據(jù)和基于數(shù)據(jù)的操作封裝在一起碘赖,使其構(gòu)成一個不可分割的獨立實體,數(shù)據(jù)被保護在抽象數(shù)據(jù)類型的內(nèi)部外构,盡可能地隱藏內(nèi)部的細節(jié)普泡,只保留一些對外接口使之與外部發(fā)生聯(lián)系。系統(tǒng)的其他對象只能通過包裹在數(shù)據(jù)外面的已經(jīng)授權(quán)的操作來與這個封裝的對象進行交流和交互审编。也就是說用戶是無需知道對象內(nèi)部的細節(jié)(當然也無從知道)撼班,但可以通過該對象對外的提供的接口來訪問該對象。
對于封裝而言垒酬,一個對象它所封裝的是自己的屬性和方法砰嘁,所以它是不需要依賴其他對象就可以完成自己的操作。
使用封裝有三大好處:
1勘究、良好的封裝能夠減少耦合矮湘。
2、類內(nèi)部的結(jié)構(gòu)可以自由修改口糕。
3缅阳、可以對成員進行更精確的控制。
4景描、隱藏信息十办,實現(xiàn)細節(jié)。
首先我們先來看兩個類:Husband.java超棺、Wife.java
publicclassHusband?{
/*
*?對屬性的封裝
*?一個人的姓名向族、性別、年齡棠绘、妻子都是這個人的私有屬性
*/
privateString?name?;
privateString?sex?;
privateintage?;
privateWife?wife;
/*
*?setter()件相、getter()是該對象對外開發(fā)的接口
*/
publicString?getName()?{
returnname;
}
publicvoidsetName(String?name)?{
this.name?=?name;
}
publicString?getSex()?{
returnsex;
}
publicvoidsetSex(String?sex)?{
this.sex?=?sex;
}
publicintgetAge()?{
returnage;
}
publicvoidsetAge(intage)?{
this.age?=?age;
}
publicvoidsetWife(Wife?wife)?{
this.wife?=?wife;
}
}
publicclassWife?{
privateString?name;
privateintage;
privateString?sex;
privateHusband?husband;
publicString?getName()?{
returnname;
}
publicvoidsetName(String?name)?{
this.name?=?name;
}
publicString?getSex()?{
returnsex;
}
publicvoidsetSex(String?sex)?{
this.sex?=?sex;
}
publicvoidsetAge(intage)?{
this.age?=?age;
}
publicvoidsetHusband(Husband?husband)?{
this.husband?=?husband;
}
publicHusband?getHusband()?{
returnhusband;
}
}
從上面兩個實例我們可以看出Husband里面wife引用是沒有g(shù)etter()的,同時wife的age也是沒有g(shù)etter()方法的弄唧。至于理由我想各位都懂的适肠,男人嘛深屋藏嬌妻嘛,沒有那個女人愿意別人知道她的年齡候引。
所以封裝把一個對象的屬性私有化,同時提供一些可以被外界訪問的屬性的方法敦跌,如果不想被外界方法澄干,我們大可不必提供方法給外界訪問逛揩。但是如果一個類沒有提供給外界訪問的方法,那么這個類也沒有什么意義了麸俘。比如我們將一個房子看做是一個對象辩稽,里面的漂亮的裝飾,如沙發(fā)从媚、電視劇逞泄、空調(diào)、茶桌等等都是該房子的私有屬性拜效,但是如果我們沒有那些墻遮擋喷众,是不是別人就會一覽無余呢?沒有一點兒隱私紧憾!就是存在那個遮擋的墻到千,我們既能夠有自己的隱私而且我們可以隨意的更改里面的擺設(shè)而不會影響到其他的。但是如果沒有門窗赴穗,一個包裹的嚴嚴實實的黑盒子憔四,又有什么存在的意義呢?所以通過門窗別人也能夠看到里面的風景般眉。所以說門窗就是房子對象留給外界訪問的接口了赵。
通過這個我們還不能真正體會封裝的好處。現(xiàn)在我們從程序的角度來分析封裝帶來的好處甸赃。如果我們不使用封裝斟览,那么該對象就沒有setter()和getter(),那么Husband類應(yīng)該這樣寫:
publicclassHusband?{
publicString?name?;
publicString?sex?;
publicintage?;
publicWife?wife;
}
我們應(yīng)該這樣來使用它:
Husband?husband?=newHusband();
husband.age?=30;
husband.name?="張三";
husband.sex?="男";//貌似有點兒多余
但是那天如果我們需要修改Husband辑奈,例如將age修改為String類型的呢苛茂?你只有一處使用了這個類還好,如果你有幾十個甚至上百個這樣地方鸠窗,你是不是要改到崩潰妓羊。如果使用了封裝,我們完全可以不需要做任何修改稍计,只需要稍微改變下Husband類的setAge()方法即可躁绸。}
publicclassHusband?{
/*
*?對屬性的封裝
*?一個人的姓名、性別臣嚣、年齡净刮、妻子都是這個人的私有屬性
*/
privateString?name?;
privateString?sex?;
privateString?age?;/*?改成?String類型的*/
privateWife?wife;
publicString?getAge()?{
returnage;
}
publicvoidsetAge(intage)?{
//轉(zhuǎn)換即可
this.age?=?String.valueOf(age);
}
/**?省略其他屬性的setter、getter?**/
其他的地方依然那樣引用(husband.setAge(22))保持不變硅则。
到了這里我們確實可以看出淹父,封裝確實可以使我們?nèi)菀椎匦薷念惖膬?nèi)部實現(xiàn),而無需修改使用了該類的客戶代碼怎虫。
我們在看這個好處:可以對成員變量進行更精確的控制暑认。
還是那個Husband困介,一般來說我們在引用這個對象的時候是不容易出錯的,但是有時你迷糊了蘸际,寫成了這樣:
Husband?husband?=newHusband();
husband.age?=300;
也許你是因為粗心寫成了座哩,你發(fā)現(xiàn)了還好,如果沒有發(fā)現(xiàn)那就麻煩大了粮彤,逼近誰見過300歲的老妖怪案睢!
但是使用封裝我們就可以避免這個問題导坟,我們對age的訪問入口做一些控制(setter)如:
publicclassHusband?{
/*
*?對屬性的封裝
*?一個人的姓名屿良、性別、年齡乍迄、妻子都是這個人的私有屬性
*/
privateString?name?;
privateString?sex?;
privateintage?;/*?改成?String類型的*/
privateWife?wife;
publicintgetAge()?{
returnage;
}
publicvoidsetAge(intage)?{
if(age?>120){
System.out.println("ERROR:error?age?input....");//提示錯誤信息
}else{
this.age?=?age;
}
}
/**?省略其他屬性的setter管引、getter?**/
}
上面都是對setter方法的控制,其實通過使用封裝我們也能夠?qū)ο蟮某隹谧龀龊芎玫目刂拼沉健@缧詣e我們在數(shù)據(jù)庫中一般都是已1褥伴、0方式來存儲的,但是在前臺我們又不能展示1漾狼、0重慢,這里我們只需要在getter()方法里面做一些轉(zhuǎn)換即可。
[java]view plaincopy
publicString?getSexName()?{
if("0".equals(sex)){
sexName?="女";
}
elseif("1".equals(sex)){
sexName?="男";
}
else{
sexName?="人妖???";
}
returnsexName;
}
在使用的時候我們只需要使用sexName即可實現(xiàn)正確的性別顯示逊躁。同理也可以用于針對不同的狀態(tài)做出不同的操作似踱。
publicString?getCzHTML(){
if("1".equals(zt)){
czHTML?="啟用";
}
else{
czHTML?="禁用";
}
returnczHTML;
}
繼承 - 在一個class類中完成特定功能的封裝充當父類 - 子類繼承它 - 子類有父類全部的特點,也會有自己衍生的特點 -
多態(tài) - 父類的引用指向子類的實例 - 根據(jù)場景不同 - 引用執(zhí)行不同的子類方法 -
接口 - interface - 內(nèi)部定義各種抽象方法 - 使用該接口的類必須重寫抽象方法
抽象類 - abstract -
接口和內(nèi)部類為我們提供了一種將接口與實現(xiàn)分離的更加結(jié)構(gòu)化的方法稽煤。
我們都知道在面向?qū)ο蟮念I(lǐng)域一切都是對象核芽,同時所有的對象都是通過類來描述的,但是并不是所有的類都是來描述對象的酵熙。如果一個類沒有足夠的信息來描述一個具體的對象轧简,而需要其他具體的類來支撐它,那么這樣的類我們稱它為抽象類匾二。比如new Animal()哮独,我們都知道這個是產(chǎn)生一個動物Animal對象,但是這個Animal具體長成什么樣子我們并不知道察藐,它沒有一個具體動物的概念皮璧,所以他就是一個抽象類,需要一個具體的動物分飞,如狗悴务、貓來對它進行特定的描述,我們才知道它長成啥樣浸须。
在面向?qū)ο箢I(lǐng)域由于抽象的概念在問題領(lǐng)域沒有對應(yīng)的具體概念惨寿,所以用以表征抽象概念的抽象類是不能實例化的邦泄。
同時删窒,抽象類體現(xiàn)了數(shù)據(jù)抽象的思想裂垦,是實現(xiàn)多態(tài)的一種機制。它定義了一組抽象的方法肌索,至于這組抽象方法的具體表現(xiàn)形式有派生類來實現(xiàn)蕉拢。同時抽象類提供了繼承的概念,它的出發(fā)點就是為了繼承诚亚,否則它沒有存在的任何意義晕换。所以說定義的抽象類一定是用來繼承的,同時在一個以抽象類為節(jié)點的繼承關(guān)系等級鏈中站宗,葉子節(jié)點一定是具體的實現(xiàn)類闸准。(不知這樣理解是否有錯!!!高手指點….)
在使用抽象類時需要注意幾點:
1、抽象類不能被實例化梢灭,實例化的工作應(yīng)該交由它的子類來完成夷家,它只需要有一個引用即可。
2敏释、抽象方法必須由子類來進行重寫库快。
3、只要包含一個抽象方法的抽象類钥顽,該方法必須要定義成抽象類义屏,不管是否還包含有其他方法。
4蜂大、抽象類中可以包含具體的方法闽铐,當然也可以不包含抽象方法。
5奶浦、子類中的抽象方法不能與父類的抽象方法同名兄墅。
6、abstract不能與final并列修飾同一個類财喳。
7察迟、abstract 不能與private、static耳高、final或native并列修飾同一個方法扎瓶。
創(chuàng)建抽象類和抽象方法非常有用,因為他們可以使類的抽象性明確起來,并告訴用戶和編譯器打算怎樣使用他們.抽象類還是有用的重構(gòu)器,因為它們使我們可以很容易地將公共方法沿著繼承層次結(jié)構(gòu)向上移動。(From:Think in java )
二泌枪、接口
接口是一種比抽象類更加抽象的“類”概荷。這里給“類”加引號是我找不到更好的詞來表示,但是我們要明確一點就是碌燕,接口本身就不是類误证,從我們不能實例化一個接口就可以看出继薛。如new Runnable();肯定是錯誤的,我們只能new它的實現(xiàn)類愈捅。
接口是用來建立類與類之間的協(xié)議遏考,它所提供的只是一種形式,而沒有具體的實現(xiàn)蓝谨。同時實現(xiàn)該接口的實現(xiàn)類必須要實現(xiàn)該接口的所有方法灌具,通過使用implements關(guān)鍵字,他表示該類在遵循某個或某組特定的接口譬巫,同時也表示著“interface只是它的外貌咖楣,但是現(xiàn)在需要聲明它是如何工作的”。
接口是抽象類的延伸芦昔,java了保證數(shù)據(jù)安全是不能多重繼承的诱贿,也就是說繼承只能存在一個父類,但是接口不同咕缎,一個類可以同時實現(xiàn)多個接口珠十,不管這些接口之間有沒有關(guān)系,所以接口彌補了抽象類不能多重繼承的缺陷锨阿,但是推薦繼承和接口共同使用宵睦,因為這樣既可以保證數(shù)據(jù)安全性又可以實現(xiàn)多重繼承。
在使用接口過程中需要注意如下幾個問題:
1墅诡、個Interface的方所有法訪問權(quán)限自動被聲明為public壳嚎。確切的說只能為public,當然你可以顯示的聲明為protected末早、private烟馅,但是編譯會出錯!
2然磷、接口中可以定義“成員變量”郑趁,或者說是不可變的常量,因為接口中的“成員變量”會自動變?yōu)闉閜ublic static final姿搜」讶螅可以通過類命名直接訪問:ImplementClass.name。
3舅柜、接口中不存在實現(xiàn)的方法梭纹。
4、實現(xiàn)接口的非抽象類必須要實現(xiàn)該接口的所有方法致份。抽象類可以不用實現(xiàn)变抽。
5、不能使用new操作符實例化一個接口,但可以聲明一個接口變量绍载,該變量必須引用(refer to)一個實現(xiàn)該接口的類的對象诡宗。可以使用 instanceof 檢查一個對象是否實現(xiàn)了某個特定的接口击儡。例如:if(anObject instanceof Comparable){}塔沃。
6、在實現(xiàn)多接口的時候一定要避免方法名的重復曙痘。
三芳悲、抽象類與接口的區(qū)別
盡管抽象類和接口之間存在較大的相同點立肘,甚至有時候還可以互換边坤,但這樣并不能彌補他們之間的差異之處。下面將從語法層次和設(shè)計層次兩個方面對抽象類和接口進行闡述谅年。
3.1語法層次
在語法層次茧痒,java語言對于抽象類和接口分別給出了不同的定義
抽象類方式中,抽象類可以擁有任意范圍的成員數(shù)據(jù)融蹂,同時也可以擁有自己的非抽象方法旺订,但是接口方式中,它僅能夠有靜態(tài)超燃、不能修改的成員數(shù)據(jù)(但是我們一般是不會在接口中使用成員數(shù)據(jù))区拳,同時它所有的方法都必須是抽象的。在某種程度上來說意乓,接口是抽象類的特殊化樱调。
對子類而言,它只能繼承一個抽象類(這是java為了數(shù)據(jù)安全而考慮的)届良,但是卻可以實現(xiàn)多個接口笆凌。
3.2設(shè)計層次
上面只是從語法層次和編程角度來區(qū)分它們之間的關(guān)系,這些都是低層次的士葫,要真正使用好抽象類和接口乞而,我們就必須要從較高層次來區(qū)分了。只有從設(shè)計理念的角度才能看出它們的本質(zhì)所在慢显。一般來說他們存在如下三個不同點:
1爪模、 抽象層次不同。抽象類是對類抽象荚藻,而接口是對行為的抽象屋灌。抽象類是對整個類整體進行抽象,包括屬性鞋喇、行為声滥,但是接口卻是對類局部(行為)進行抽象。
2、 跨域不同落塑。抽象類所跨域的是具有相似特點的類纽疟,而接口卻可以跨域不同的類。我們知道抽象類是從子類中發(fā)現(xiàn)公共部分憾赁,然后泛化成抽象類污朽,子類繼承該父類即可,但是接口不同龙考。實現(xiàn)它的子類可以不存在任何關(guān)系蟆肆,共同之處。例如貓晦款、狗可以抽象成一個動物類抽象類炎功,具備叫的方法。鳥缓溅、飛機可以實現(xiàn)飛Fly接口蛇损,具備飛的行為,這里我們總不能將鳥坛怪、飛機共用一個父類吧淤齐!所以說抽象類所體現(xiàn)的是一種繼承關(guān)系,要想使得繼承關(guān)系合理袜匿,父類和派生類之間必須存在"is-a"
關(guān)系更啄,即父類和派生類在概念本質(zhì)上應(yīng)該是相同的。對于接口則不然居灯,并不要求接口的實現(xiàn)者和接口定義在概念本質(zhì)上是一致的祭务, 僅僅是實現(xiàn)了接口定義的契約而已。
3穆壕、 設(shè)計層次不同待牵。對于抽象類而言,它是自下而上來設(shè)計的喇勋,我們要先知道子類才能抽象出父類缨该,而接口則不同,它根本就不需要知道子類的存在川背,只需要定義一個規(guī)則即可贰拿,至于什么子類、什么時候怎么實現(xiàn)它一概不知熄云。比如我們只有一個貓類在這里膨更,如果你這是就抽象成一個動物類,是不是設(shè)計有點兒過度缴允?我們起碼要有兩個動物類荚守,貓珍德、狗在這里,我們在抽象他們的共同點形成動物抽象類吧矗漾!所以說抽象類往往都是通過重構(gòu)而來的锈候!但是接口就不同,比如說飛敞贡,我們根本就不知道會有什么東西來實現(xiàn)這個飛接口泵琳,怎么實現(xiàn)也不得而知,我們要做的就是事前定義好飛的行為接口誊役。所以說抽象類是自底向上抽象而來的获列,接口是自頂向下設(shè)計出來的。
四蛔垢、總結(jié)
1击孩、 抽象類在java語言中所表示的是一種繼承關(guān)系,一個子類只能存在一個父類啦桌,但是可以存在多個接口溯壶。
2、 在抽象類中可以擁有自己的成員變量和非抽象類方法甫男,但是接口中只能存在靜態(tài)的不可變的成員數(shù)據(jù)(不過一般都不在接口中定義成員數(shù)據(jù)),而且它的所有方法都是抽象的验烧。
3板驳、抽象類和接口所反映的設(shè)計理念是不同的,抽象類所代表的是“is-a”的關(guān)系碍拆,而接口所代表的是“l(fā)ike-a”的關(guān)系若治。
抽象類和接口是java語言中兩種不同的抽象概念,他們的存在對多態(tài)提供了非常好的支持感混,雖然他們之間存在很大的相似性端幼。但是對于他們的選擇往往反應(yīng)了您對問題域的理解。只有對問題域的本質(zhì)有良好的理解弧满,才能做出正確婆跑、合理的設(shè)計。
以上 不是我寫 - 是從網(wǎng)上找的 - 我覺得很有道理 - 哈哈 自己寫不出來 --