iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 3
2
自我挑戰組

來讀設計模式:Junior developer 跟大家一起練功系列 第 3

DAY3: 從物件導向範型談起2

這篇繼續 DAY2 的例子,在上篇的結尾,我們對物件導向範型的解法提出了另一項需求:在聽課的人中,研究生中有擔任助教的人必須要先到行政處找行政人員辦理一些業務。面對這項新的需求,我們該如何應對?

抽象類別的加入

現在遇到的問題是除了「一般學生 (RegularStudent) 」之外,還有「研究所學生 (GraduateStudent) 」,面對這項新需求,我們必須讓這兩種學生實體化後能夠都被納入蒐集學生的集合內(物件導向範型的流程 step2)。

解決方案 —— 定義抽象類別

解決的方案就是做出一個包含 RegurlarStudentGraduateStudentStudent,我們稱 Student 類別為抽象類別 (Abstract Class)

這個例子,RegularStudent 是一種 StudentGraduateStudent 也是一種 Student。這種關係是繼承 (Inheritance) 中的一種特例,稱作 is-a 關係

這樣的關係有很多種稱呼方式,我們可以說「GraduateStudent 繼承 Student」、「GraduateStudentStudent 的子類別」等等。

如何理解抽象類別

多數人對抽象類別的理解是「不能被實體化的類別」,包括我在還沒讀這本書前,也是這樣子理解。

但本書提到一個有趣的形容方式:

抽象類別可以充當其他類別的「占位符號」(placeholder) 。可以使用抽象類別定義其衍生類別必須實作的方法。

前者是用實作的層次上去看待它;後者則是在概念層次去理解它。

Placeholder 就像是下圖這樣,在網站上填寫一些基本資料的時候 input 裡的暗示你的字,像是在姓名欄位顯示 "Your name" 來告訴你這裡要填名字。

它某種程度規範了你必須要填寫的字(必須實作的method),但你仍然有權力去寫自己想寫的東西(method 實作的行為由衍生類別自己決定)。

再多談一些

多型

本書作者對「多型 (polymorphism) 」的描述如下:

在物件導向語言中,我們經常用抽象類別的參照來參照物件。但是,我們真正參照的是從抽象類別衍生的類別的具體實體。

因此,當我透過抽象參照概念性地要求物件做什麼時,將得到不同的行為,具體行為取決於衍生物件的具體類型。

看起來十分拗口⋯但其實很好理解,從上面學生的例子來說,講師跟同學說「去下間教室」,每位學生會根據類型不同而採取不同的行為。而這個現象就是多型。

可視性與封裝

可視性源自於物件的特性 —— 物件自己負責自己,也因為如此,很多東西不需要讓其他物件知道。

例如說,學生小明沒有必要把他家狗的名字告訴給講師知道(有可能他家的狗叫 null)。

可視性也可以理解成被其他物件的可存取性,那麼,就會有以下三類:

  • 公開 (public):任何物件都能看見
  • 保護 (protected):只有該類別的物件與它的衍生類別的物件能夠看見
  • 私有 (private):只有該類別的物件能看見

也因為有些資料元素和 methods 對外是隱藏的,這就引出了「封裝 (encapsulation) 」的概念。封裝就是一種資料隱藏,但其實不僅止於此,它甚至可以指涉各種隱藏

例如,講師不知道小明到底是一般學生還是研究生。所以學生的類型對講師隱藏了;從物件導向語言來說,抽象類別 Student 隱藏了從其衍生的類別的類型。

封裝帶來的好處

封裝給我們的好處有幾點:

  • 使用某物件時,不需要擔心它的行為的實作問題。物件內部行為的變化對其他物件而言是不可見的;
  • 物件自己負責的責任變多,控制程式需要負的責任就變少;
  • 將許多不同的責任透過封裝隔開,也把兩種不同的物件彼此帶來的變化給隔開來。
  • 封裝(隱藏實作)有助於降低耦合。

建構函數與解構函數

建構函數 (constructor) 是物件被建立時一定會被呼叫的一個 method,它負責初始化、設定預設資訊、設定與其他物件關係或建立物件所需的其他工作的天然場所。

相反地,當一個物件不再存在或不需要再被使用到時,就會呼叫一個摧毀該物件的 method,它稱為解構函數(destructor)

接下來

下一篇我將會提到不同類別之間的關係,文章長度不夠的話也許還會提到一些設計模式的簡介(chapter 5)。


上一篇
DAY2: 從物件導向範型談起1
下一篇
DAY4: 類別間的關係
系列文
來讀設計模式:Junior developer 跟大家一起練功22

尚未有邦友留言

立即登入留言