l

2014年5月23日 星期五

談談壞味道(14):Refused Bequest

May 20 11:26~12:55

螢幕截圖 2014-05-20 13.02.45

 

Refused Bequest(被拒絕的遺贈)

Refused是「拒絕」的意思,bequest是「遺贈」、「遺產」的意思。這兩個字合起來,就是「被拒絕的遺贈」,也就是說有人把你指定為「保險(遺贈)受益人」,但是你卻拒絕接受這份「大禮」。套用物件導向的術語,如果你的繼承違反了Liskov Substitution Principle,就出現了這個壞味道。

Teddy一直覺得《Refactoring》這本書對於某些壞味道的解釋讓人讀起來不是那麼容易理解,Refused Bequest這個壞味道也是其中一個。還好有《Refactoring Workbook》這本書可以參考,這本書提到Refused Bequest壞味道的幾點「病徵」:

  • 子類別沒有實作繼承自父類別的函數,學過Composite設計模式的鄉民,對於這一點應該不陌生,Leaf繼承自Component,但卻沒有實作定義在Component身上的Add、Remove、getChild函數。針對這些繼承而來卻未加實作的函數,如果子類別直接丟出exception,則屬於「honest refusal(誠實拒絕)」,如果僅提供空的實作(就是什麼事都沒做),則屬於「implicit refusal(隱式拒絕)」。

螢幕截圖 2014-05-20 12.07.28

GoF的Compoiste設計模式

  • 客戶端直接使用子類別型態的變數(reference或是pointer),而非透過父類別型態的變數來存取子類別。翻譯成白話文就是說,雖然有繼承架構,但是並沒有透過多形(polymorphism)的方式來操作子類別。
  • 根本錯用繼承(認賊作父?!),子類別和父類別不存在 is-a的關係。例如,貓去繼承狗,或是大象去繼承老鼠。

《Refactoring》書中提到如果這個壞味道不是很「濃烈」,Composite設計模式就屬於這種例子,便可以放著不用管它。但如果是錯用繼承的情況,就不能視而不見。

***

Refused Bequest之所以會是一個bad smell的原因可歸類為:understandability和modifiability這兩點。

移除Refused Bequest壞味道的方法,在《Refactoring》書中提到可以套用Replace Inheritance with Delegation、Extract Subclass、Push Down Field、Push Down Method。

***

友藏內心獨白:剩下最後一個壞味道。

沒有留言:

張貼留言