天吶,你還記得java特性:封裝、繼承、多態,是個啥嗎

前言

首先看到這個標題,大家可能覺得很無聊,這三個詞可以說基本上隨便一搜,就一大堆文章解釋的頭頭是道,但是即便如此,我爲啥還是要寫這篇文章呢,是因爲今天在給大家準備後續內容時,無意看到了這三個詞,然後順帶想了一下各自的含義,發現封裝和繼承還比較好理解,結果另外一個多態琢磨了半天,竟然一時忘了這個詞的含義,突然有點愕然,自己才工作了一年,居然很多基礎概念都快記不清了,oh,太可怕了!於是纔有了這篇文章,一方面提醒自己,一方面也分享出來給大家,讓大家也不能忘記哦。

正文

1、封裝

封裝在這三個詞裏面是最容易理解的,專業術語我就不多說了,因爲說了你們也記不住,我也記不住,在我看來,最容易理解的方法就是舉例,OK,那我們就舉個例子,比如現在我希望有一個類,這個類有一些屬性和功能,並且可以完成一些,比如

  • 有眼睛,屬性
  • 有嘴巴,屬性
  • 可以喫飯,功能
  • 可以睡覺,功能
  • 心上人,屬性
  • ······

屬性就相當於是這個類擁有的成員變量,這個變量的值就對應具體的屬性,比如眼睛,有單眼皮、雙眼皮,這個很好理解。功能就相當於是這個類擁有的方法,比如喫飯、睡覺,都是在執行某個動作,也就是類的某個方法的執行。然後還有一些訪問權限控制,比如心上人這個屬性,這個類可能不希望其它對象知道,所以這個屬性就是私有的,也就相當於java裏的private訪問權限。

通過上面說的一些要素,成員變量、方法、訪問控制等,我們就可以拼湊出一個簡單的類來了,不用我說,大家應該也知道了這個類就是:可愛的你。而定義這些要素以及拼湊的過程就是封裝

現在我們明白了封裝的意思,但是這樣做可以帶來哪些好處呢,爲啥無緣無故要封裝這個封裝那個的,這是因爲封裝後,這個類對象,外界只會知道它暴露出來的屬性或者方法,此外,對於方法,外界只知道該類對象有這個方法,比如可以喫飯,但是並不知道該方法的細節,比如喫的什麼、在哪裏喫的等這些細節。那隱藏這些細節或者屬性有啥用呢,藏着掖着的有啥好處嗎,當然是有好處的,比如喫飯這個方法,裏面需要用到筷子這個屬性,但是假設由於我沒有隱藏筷子這個屬性,導致該屬性被外界修改了,現在只有一隻筷子了,所以這飯也沒法吃了,最終喫飯失敗。

2、繼承

這個詞也比較簡單,很好理解,同樣的方法,我們還是通過舉例來簡單說明一下,比如現在想喫點水果,但是不知道喫什麼,平常喫的比較多的可能就是蘋果、香蕉、橘子、荔枝等,一番糾結後選擇了口感最好的荔枝。OK,在這個場景下,就可以抽取一個典型的繼承模型出來,對於水果,可以理解爲它有一個屬性:可以被喫。對於蘋果、香蕉、橘子、荔枝,它們也和水果一樣,有一個同樣的屬性:可以被喫,但是它們除了這個屬性之外,還擁有一些不同的屬性,比如蘋果是青色,香蕉是黃色、橘子是橙色、荔枝是深紅色等,這些屬性是水果這個對象所沒有的,所以我們可以將特有的屬性定義在蘋果、香蕉、橘子、荔枝中,對於公共的屬性:可以被喫,我們選擇去繼承水果這個對象,來讓蘋果、香蕉、橘子、荔枝通過繼承的方式獲取屬性:可以被喫。這就是繼承

那說了半天,好像確實明白了繼承的意思,那這樣做的意義何在呢,意義就在於對於一些有公共屬性的對象,無需重複在各自內部定義屬性,只需要定義一個父類對象,然後在父類對象裏定義這些公共屬性,然後其它的類就只需要負責各自特有的屬性定義,公共的屬性通過繼承的方式一次搞定。

3、多態

這個詞相對前兩個,看上去就感覺高級一點,也沒那麼容易一下子就理解,但是如果擴展爲:多種形態,這樣的描述方式是不是就容易理解一點,那再擴展一下描述:一個類可能存在多種形態,是不是又清晰了一點,好像就是在說父子類的關係,所以這裏不難想到上面說的繼承,但是它既然作爲一個單獨的詞,肯定有另外的意義所在,要理解這個詞的含義,我還是一樣的方法,舉個例子,但是不是中文描述,雖然中文描述可以說清,但是不好理解,所以我就直接舉一行代碼:

Person person = new ZhangSan();

Person是一個父類,裏面有一個方法eat()代表喫米飯,ZhangSanPerson的一個子類,它重寫了父類的方法eat()代表喫披薩,並且還有一個單獨的方法swim()代表游泳。它們的定義如下

class Person{
	public void eat(){
    System.out.println("喫米飯");
  }
}
class ZhangSan extend Person{
  @Override
	public void eat(){
    System.out.println("喫披薩");
  }
  
  public void swim(){
    System.out.println("我會游泳");
  }
}

這種情況下,我們如果調用例子中的person.eat(),會出現什麼樣的情況呢,通過運行,我們發現了最終結果是:喫披薩,而這個結果就是多態的一種體現,因爲我們在聲明的時候,明明只是聲明瞭一個父類對象,結果卻調用到了子類的方法,原因就是因爲我們是用子類來初始化的,如果子類重寫了父類的方法,那用子類初始化的父類對象就會調用子類的實現方法,emmmmm,這句話可能有點繞,總之不理解的時候,想想上面的例子就明白了。

在上面的例子中,如果再來一個對象LiSi或者WangWu,也分別繼承Person,並重寫eat()方法,以及添加各自的特性方法,那麼Person person = new ZhangSan();Person person = new Lisi();Person person = new WangWu();,以及類似這樣的代碼,就可以理解爲Person這個類能以ZhangSan Lisi WangWu這三種形式存在,也就是我們上面說的,一個類存在多種形態,也就是多態,怎麼樣,明白了嗎。

OK,現在我們明白了多態是什麼,那這樣設計的意義何在呢,好像只是給人感覺很繞,但是沒有什麼用武之地,其實之所以這樣想,還是因爲對平常的代碼沒有仔細觀察和思考,當然你可能也已經正在用這個特性來開發代碼,只不過你不知道這個特性叫多態而已,在實際開發中,接口和抽象類其實就是多態最爲直接的一種使用體現,舉個很簡單的例子,比如:張三現在需要回家,一般是滴滴打車回家。在這樣一個簡單的場景中,我們定義一個類ZhangSan,添加一個方法goHome去執行這個回家的操作,回家過程中需要選擇一種交通方式才能回家,我們默認是滴滴打車回家,所以最終定義如下:

class ZhangSan{
  TrafficWay trafficWay = new DiDi();
	void goHome(){
    trafficWay.go();
  }
  
  void setTrafficWay(TrafficWay way){
    trafficWay = way;
  }
}
interface TrafficWay{
  void go();
}
class DiDi implements TrafficWay{
  void go{
    System.out.println("滴滴打車回家");
  }
}

但是有一天加班太晚打不到車了,沒辦法ZhangSan這次只能坐地鐵回家,這時我們只需新增一個TrafficWay接口的實現類,再給ZhangSan設置進去即可,

class SubWay implements TrafficWay{
  void go{
    System.out.println("坐地鐵回家");
  }
}
ZhangSan zs = new ZhangSan();
zs.setTrafficWay(new SubWay());
zs.goHome();

同樣的,假設地鐵也停運了,那ZhangSan只能走路回家了,我們同樣的也只需要新增一個TrafficWay接口的實現類Walk,而無需修改以前的代碼,就達到了效果。在該例子中,相信也不用我多說了吧,TrafficWay這個接口就是一個多態的體現,能以DiDiSubWayWalk等各種形態存在,用來滿足不同情形的需求。

這就是多態的實際應用場景。怎麼樣,明白了嗎,是不是發現原來我們平常看到的這些設計方式,原來就是多態的一種思想,這種思想一般用在框架設計上面,哪一天我們需要設計一個框架,就可以用這個思想啦。

結語

最後,我想感嘆下,雖然這三個詞在我們最初學java的時候,就會去了解學習,但是我們從java使用到現在,真真正正理解並且將這些特性思想融入到實際開發中的,又有多少呢,有時候我們只是沉浸於各種業務開發,而忽略了一些優秀的設計思路或方法,好了,今天就到這吧,本篇應該只算是一個java基礎知識的複習,後續內容盡請期待哦,下次見!!!

=========================================
另外,本文章也會同步發佈在本人的公衆號上面哦,歡迎關注呀,公衆號裏會優先推送最新的文章,還有各種送書等福利,以及各種小驚喜,怎麼樣,快來關注呀!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章