面試官:淦!0202年你還不知道面向對象?
- 2020 年 6 月 15 日
- 筆記
- Java Grammar
2020年6月13日 多雲轉暴雨⛈️
I’m
sad,tired,negative,powerless,miss,lonelyfine 🙂
那你回去等通知吧
面試官:我看你簡歷上說,你的主要程式語言是Java,偶爾也用Python,那麼你可以說一下這兩個的相同點在什麼地方嗎?
山禾:它們都是高級程式設計語言,都是面向對象的語言。
面試官:那你講講你是怎麼理解面向對象的吧。
山禾:emmm。。封裝,繼承,多態是面向對象的三大特徵。
面試官:還有其他要補充的嗎?
山禾:沒了
面試官:那你回去等通知吧。
是什麼
痛定思痛,挫折只會讓我變得更強,奧利給!下面開始進入正文,首先我們需要知道面向對象是什麼?
面向對象,顧名思義,是面向對象,也就是說單身狗是不配使用面向對象的程式語言的(當然只是開個玩笑,逃)。
對象,就是把現實世界中的實物映射抽象到虛擬世界中,把實物的屬性和行為,通過程式碼的方式表達出來。然後通過設計對象的數據結構(屬性),然後使用演算法進行行為的模擬(方法),就完成了從現實到虛擬的一個映射。
實體 | 對象 | 類 |
---|---|---|
屬性 | 數據結構 | 變數 |
行為 | 演算法 | 方法 |
與面向對象經常拿來對比的就是面向過程編程,那麼他們之間的區別在什麼地方呢?
面向過程和面向對象
面向過程編程,打個比方,我們買過的一般的玩具(變形金剛),我們必須要按照它說明書上的步驟,一步一步的去組裝,才能得到最後的玩具,如果我們想要一個新的玩具,就要去商場買一個新的,然後按照說明書的順序一步一步的組裝。
而面向對象編程,就可以理解為積木,沒有一個固定的拼裝方式,我們可以發揮自己的想像力,去自由的拼裝和組裝,同樣的模組在不同的地方可以起到不同的作用(多態),一塊兒積木就是一個最小的單位,我們不用去關心積木是怎麼造的(封裝)。也可以用多個對象組裝起來去拼裝成一個新的對象(繼承)。大大的方便了我們的設計,不再拘泥於過程,極大程度上的放飛了生產力和效率。
為什麼
我們剛剛已經了解了面向對象是什麼,下面我們來說一下,為什麼要用面向對象編程
-
首先從理解角度上來說,它符合我們對現實世界的認知習慣,更容易去理解、實現和設計我們的需求。
-
其次從軟體設計的角度上來說,行為的實現對於外部是完全封閉的,只需要提供對應的介面就可以獲得相應的結果,降低了程式碼與程式碼之間的耦合度。符合我們高內聚,低耦合的設計理念。優雅,客觀,層次分明,像積木一樣,可以方便的實現插拔和維護,對象組合而成的模組化和服務化,更是大大擴展了系統的伸縮性,便於維護、擴展和復用。這也是為什麼越來越多的程式語言選擇向這個方向去靠攏( TypeScript說的就是你
怎麼用
剛剛我一直忍住,沒有去提面向對象的三大特性:封裝、繼承和多態,我相信我們有一些經驗的開發人員來說,這三個詞語是再熟悉不過了。下面,我通過程式碼的方式,來看看這三個特性在程式碼中的模擬應用。
封裝
@Data
public class Uzi {
// 選手類型
private String type;
// 選手最擅長英雄
private String bestHero;
// 選手狀態
private Status status;
public void play() {
status.say();
}
}
public class Status {
public void say(){}
}
上面是一段非常簡單的程式碼,我定義了一個很簡單的類,裡面的name
,type
,bestHero
對於我們來說都是一個包裝在盒子里的東西。比如:
Uzi uzi = new Uzi();
uzi.setType("ADC");
uzi.setBestHero("孫尚香");
我們看到的Uzi可能就是一個主玩孫尚香的職業ADC選手(🐶狗頭保命,我啥都不知道),他怎麼玩的,我們不需要知道,我們只需要知道他這樣的一名選手就可以了。這就是封裝的魅力:
-
隱藏了實現的細節,提供對外的訪問方式。 -
外部如果想要訪問,必須經過這個方法。
繼承
看完了封裝,下面我們來看繼承,我們分別用三個狀態去繼承Status類:
public class ShunFeng extends Status {
@Override
public void say(){
System.out.println("順風狂小狗");
}
}
public class NiFeng extends Status {
@Override
public void say(){
System.out.println("逆風簡自豪");
}
}
public class JueJing extends Status {
@Override
public void say(){
System.out.println("絕境Uzi");
}
}
關鍵字extends表示正在構造的新類派生於一個已經存在類。這個已經存在的類被稱為父類(超類,基類);新創建的類被稱為子類。在通過擴展父類定義子類的時候,僅僅需要指出子類和父類的不同之處。因此在設計類的時候,應該將通用的方法放在父類中,而將具有特殊用途的方法放在子類中。
我們只是在父類Status
中定義了say方法,然後三種不同的類去繼承這個類,然後實現方法,這樣就體現出了面向對象在設計上的可擴展性,但是需要注意的是,繼承會破壞封裝,我們需要謹慎使用,盡量使用一些設計模式去避免繼承,合理使用,才能體現出它的優勢~
說完了繼承,接下來就要去說多態了。
多態
在說多態之前,我們先來看一下程式碼:
public class Test {
public static void main(String[] args) {
//uzi1
Uzi uzi1 = new Uzi();
ShunFeng shunFeng = new ShunFeng();
uzi1.setStatus(shunFeng);
//uzi2
Uzi uzi2 = new Uzi();
NiFeng niFeng = new NiFeng();
uzi2.setStatus(niFeng);
//uzi3
Uzi uzi3 = new Uzi();
JueJing jueJing = new JueJing();
uzi3.setStatus(jueJing);
//uzis
Uzi[] uzis = {uzi1,uzi2,uzi3};
// 多態
for (Uzi uzi : uzis) {
uzi.play();
}
}
}
運行程式的結果:
(TMD,淚目,👴青結)
所謂的多態就是一個對象變數(比如上文中的status變數)可以指示多種實際類型的現象(比如status既可以引用Status對象,也可以引用它的子類ShunFeng對象)被稱為多態。在運行時候能夠自動地選擇調用哪個方法的現象被稱為動態綁定,上面列印出的語句,就說明了這一點。
後續
原來我們天天掛在口邊的面向對象,其實某種程度上來說,更像是一種哲學,一種電腦科學發展的自然規則。
如果你有學到,請給我點贊👍+關注,這是對一個✊堅持原創作者的最大支援!我是山禾,千篇一律的皮囊,萬里挑一的靈魂,一個不太一樣的寫手。
世事洞明皆學問,人情練達即文章。
