物件導向簡介
什麼是物件導向程式設計?為什麼要有物件導向?在 JavaScript 中實做的例子又有些什麼呢?
本篇就來簡單探討這些問題!
什麼是物件導向程式設計?
物件導向開發的英文是 OOP (Object oriented programming),初次聽到這個名字的時候,完全不知道是什麼,既不知道物件為何、又不知道導向是在導向什麼,唯一知道的只有 Programming。
所以要了解物件導向,就得從知道什麼是「物件」開始。
Class and Object
何謂物件(Object)?其定義是類別(Class)的實例(Instance)。又出現了兩個我初學時看不懂得名詞:Class and Instance。
所以在談物件前,先來看看所謂類別(Class)的定義,便是:一件事物的抽象特點。
哇,好抽象的抽象定義呀!簡單來舉個例子,「人」是一個類別,我們可以為「人」加上一些資訊,像是有「名字」、「年齡」,並且可以「說話」。翻譯成程式碼就會像是
1 | class Person { |
其中名字(name)和年齡(age)被稱做「屬性(attribute)」,而說話(talk)被稱做「方法(method)」。
Attribute 就是這個 Class 的一些資訊,而 Method 就是這個 Class 可以做的一些事情。在代入物件導向的概念前,其實 Attribute 就是 Variable(變數)、而 Method 就是 Function(函式)。
有了 Class 的概念後,就可以進入到 Instance 及 Object 為何了!
我們知道「人」是一種抽象的 Class,那我們要使用時怎麼辦?自然要把抽象的概念實體化,實體化的產物就是一個 Object,我們可以這個 Object 為 這個 Class 的 Instance。
例如 John 是一個人,我們可以用抽象的 Class 產生出一個 Instance,這就是叫做 John 的 Object。
1 | Person john = new Person(); |
為什麼要有物件導向?
了解物件導向基礎的 Class 及 Object 後,我們來看看為何要這麼做呢?這麼做有什麼好處導致這個概念被發明出來?
根據 Wiki 的敘述,OOP 的雛形是在 1960 年代被就能被找到,而在 1980 年代逐漸成為一種主流。由於 OOP 之前的程式語言只有基本的變數、函式、條件判斷、迴圈等等概念,雖說已經可以重複利用程式碼,但在實做一些概念類似的功能時,單用 Function 無法做到太好的效果。
舉個例子來說,連接資料庫並實做一些操作這樣的事情,如果要連接兩個不同的資料庫,如 MySQL 或 PostgreSQL,我們可能可以寫一個 Function 叫做 connect,裡面傳入參數判斷是哪種資料庫:void connect(String dbType)
。
那實做讀取和寫入呢?類似 void read(String dbType)
和 void write(String dbType)
的 Function 或許也行,但是我在讀取時是否要確認 connect 的是相同的資料庫,不然 connect MySQL 卻 read PostgreSQL,不就麻煩了?
這種錯誤可能不容易犯,但是當要傳入和暫存的資訊變多的話呢?情況就會變的更複雜一些了!
這時用上 OOP 的概念可以有效簡化這些問題,像是這樣的寫法:
1 | Database mysql = new Database('localhost:3306'); |
是否感覺更清楚及容易閱讀一些呢?我們接著看看 OOP 有哪些特性!
物件導向三(四)大特性
- Encapsulation 封裝
簡單來說就是把一些資訊包起來,在使用 Instance 時你無法直接取得所有內容物,只能看公開的 Attribute 和使用公開的 Method。 - Abstraction 抽象
把現實世界的資訊轉換成一個 Class 的行為便是抽象(有些時候,這個特性不會被特別提到) - Inheritance 繼承
Class 之下可以有 Subclass,而 Subclass 可以擁有 Parent Class 的 Attribute 及 Method - Polymorphism 多型
當一個 Class 繼承另一個 Parent Class 時,此 Class 可以覆寫其 Method。如動物能生育,鳥和狗都是動物,但鳥的生育可以被實做成卵生,而狗則實做成胎生
物件導向五大原則 SOLID
- S - Single Responsibility Principle 單一功能原則
每個 Object 都只該有一個明確的功能,做到低耦合(Coupling)、高內聚(Cohesion) - O - Open Close Principle 開放封閉原則
擴充時應新增程式碼(對此開發),而非修改現有程式碼(對此封閉) - L - Liskov Substituion Principle 里氏替換原則
在替換 Subclass 時應該要可以保持程式的正確性 - I - Interface Segregation Principle 介面隔離原則
針對 Client 提出符合他們的 Inteface,改動程式碼時應讓他們可以使用原本的 Interface 而不至改變 - D - Dependency Inversion Principle 依賴反轉原則
Caller 和 Callee 應該由介面溝通,不至於 Callee 的 Code 改動會牽動到 Caller 也改