扒一扒面向對象編程的另一面
摘要:儘管有很多小夥伴對面向對象的概念已經很很熟了,但是到底什麼是面向對象編程?面向對象有哪些特性?面向對象編程能夠為我們帶來哪些便利?面向對象又有哪些不足呢?
本文分享自華為雲社區《【雲駐共創】被吹捧了很多年的面向對象編程真的就這麼完美嗎?》,作者: 冰 河 。
說到面向對象,相信很多小夥伴都已經很熟悉了,畢竟像Java、C++這種程式語言長期排在程式語言榜的前列,而且幾乎每一所大學的軟體工程專業和電腦專業都會開設Java和C++相關的課程。在上學時,老師就會給我們將什麼是對象、什麼類。比如:在Java中,萬物皆對象。
說到這兒,儘管有很多小夥伴對面向對象的概念已經很很熟了,但是到底什麼是面向對象編程?面向對象有哪些特性?面向對象編程能夠為我們帶來哪些便利?面向對象又有哪些不足呢?
很少有人深究過這些問題,相信不少小夥伴都是都是一知半解的,今天,我們就一起來聊聊面向對象這個話題。
什麼是面向對象編程?
首先,我們來聊聊什麼是面向對象編程。面向對象編程的英文是Object Oriented Programming,簡稱OOP。在面向對象中有兩個最重要,也是最基本的概念,那就是:類和對象。
這兩個概念最早出現到 Simula 程式語言中。而真正第一次使用面向對象編程這個概念的是在 Smalltalk 語言中。而 Smalltalk 語言也被公認為是世界上第一個真正意義上的面向對象程式語言。
發展到今天,面向對象的程式語言越來越多,像C++、Java、Go、Python、C#、Object-C、Scala等都是面向對象程式語言。
其實,面向對象編程和面向對象程式語言是有著本質的區別的。
面向對象編程: 面向對象編程更多的是指一種編程約束,以類和對象這兩個概念作為輸出的載體,並提供 封裝、繼承、抽象、多態 四個特性。
面向對象程式語言: 面向對象程式語言本質上就是一種輸出表達面向對象的工具,它能夠將程式設計師的所思所想轉換成電腦能夠識別的二進位碼,最終能夠在電腦上運行。
面向對象有哪些特性?
前面我們已經簡單的提及了面向對象的四大特性:封裝、繼承、抽象和多態 。
封裝
封裝,顧名思義,就是將要訪問的數據保護起來,不讓外界直接訪問類的屬性和欄位,而是對外提供有限的訪問介面,授權外部僅能通過類提供的介面進行訪問。例如,我們以Java語言為例,寫一個只包含用戶姓名userName和用戶年齡userSex的User類。
public class User{ private String userName; private Integer userSex; public void setUserName(String userName){ this.userName = userName; } public String getUserName(){ return this.userName; } public void setUserSex(Integer userSex){ this.userSex = userSex; } public Integer getUserSex(){ return this.userSex; } }
在這個User類中,總共有兩個屬性,也叫做類的成員變數,分別為userName和userSex。userName表示用戶的姓名,userSex表示用戶的名稱。
我們無法直接訪問User類中的userName和userSex屬性,因為它們都是被privaite修飾符修飾的。但是我們可以通過如下四個方法訪問者兩個屬性。
- void setUserName(String userName)
- String getUserName()
- setUserSex(Integer userSex)
- Integer getUserSex()
這種封裝特性能夠提高類的易用性,減少編程過程中程式碼出錯的風險。
繼承
繼承在程式語言里最直接的體現就是父子類的關係,在Java中使用 extends 關鍵字實現繼承,而在C++中使用冒號(:) 表示繼承關係。
例如,我們以 Java 語言為例,創建一個Student類,繼承User類,如下所示。
public class Student extends User{ private String studentNo; public void setStudentNo(String studentNo){ this.studentNo = studentNo; } public String getStudentNo{ return this.studentNo; } }
此時,Student 類對象就能夠通過 User 類對象提供的 public 方法訪問 User 類對象的屬性。
繼承最大的好處就是能夠實現程式碼的復用。
抽象
抽象主要指的是隱藏方法的具體實現,讓方法的調用者無需關心方法的具體實現,只需要關心類提供了哪些功能即可。
例如,在 Java 程式語言中,實現抽象最直觀的就是 介面和抽象類。 介面使用 interface 關鍵字修飾, 抽象類使用 abstract 關鍵字修飾。
例如,以 Java語言為例,Student 類的業務邏輯介面 StudentService 如下所示。
public interface StudentService{ public abstract Student getStudentByNO(String studentNo); }
實現 StudentService 介面的 AbstractStudent 抽象類。
public abstract class AbstractStudent{ @Override public Student getStudentByNO(String studentNo){ //省略無數程式碼 return student; } public abstract void visitStudent(String studentNo); }
抽象更多的是能夠讓程式的設計和實現分離。
多態
多態指的是子類可以替換父類,實際運行程式的程式碼時,調用子類的方法實現。例如,下面的User類和Student類。
User類:
public class User{ private String userName; private Integer userSex; public void setUserName(String userName){ System.out.println("調用User類的setUserName()方法..."); this.userName = userName; } public String getUserName(){ return this.userName; } public void setUserSex(Integer userSex){ this.userSex = userSex; } public Integer getUserSex(){ return this.userSex; } }
Student類:
public class Student extends User{ private String studentNo; public void setUserName(String userName){ System.out.println("調用Student類的setUserName()方法..."); this.userName = userName; } public void setStudentNo(String studentNo){ this.studentNo = studentNo; } public String getStudentNo{ return this.studentNo; } }
我們運行如下程式碼。
public static void main(String[] args){ User user = new Student(); user.setUserName("冰河"); }
此時,會在命令行輸出如下語句:
調用Student類的setUserName()方法...
多態最大的好處就是提高了程式的可擴展性。
面向對象編程有哪些好處?
面向對象編程是有諸多好處的,例如文章前面介紹的如下優點:
- 封裝特性能夠提高類的易用性,減少編程過程中程式碼出錯的風險。
- 繼承最大的好處就是能夠實現程式碼的復用。
- 抽象更多的是能夠讓程式的設計和實現分離。
- 多態最大的好處就是提高了程式的可擴展性。
除此之外,面向對象編程在並發領域也是由明顯的優勢的。在並發編程領域,我們可以使用面向對象的封裝特性將共享變數封裝到一個類中,並且這個共享變數使用 private 修飾,也就是說這個共享變數無法被外界直接訪問。它只能通過這個類提供的有限個方法進行訪問,並且這些方法都通過加鎖的方式保證執行緒安全。這就避免了多個執行緒同時方法這個共享變數引起的執行緒安全問題。
面向對象編程有哪些不足?
儘管面向對象編程存在著諸多的好處,但是它也有美中不足的部分。
- 萬物皆對象,大量的創建對象會佔用大量的記憶體空間。
- 需要有一定的軟體支援環境。
- 不太適用於開發一些電腦底層的應用,例如晶片開發,單片機開發等。
- 不太適用於一些大型的MIS系統的開發。
- 性能不如面向過程編程高。
- 不適合開發實時性要求特別高的指令傳輸系統。