Re: [問題] 以父類別宣告然後以子類別的建構子new

作者: cha122977 (CHA)   2014-07-20 01:26:18
部分內容恕刪
※ 引述《yoll522 (幽靈)》之銘言:
: 如果說現在要組一個team
: Team {
: 醫療忍者 m = new 綱手();
: 忍者 n = new 自來也();
: 隊長 o = new 飛猿();
: }
: 就好像說,我都知道鋼手要當醫療忍者了,也知道飛猿要當隊長
: 那為什麼寫程式時不就乾脆寫成
: Team {
: 鋼手 m = new 綱手();
: 自來也 n = new 自來也();
: 飛猿 o = new 飛猿();
: }
: 這樣呢?
: 如果忍者這父類別有一個abstract的招換術需要子類去定義他
: 那繼承忍者的所有類別,都一定會去定義招換術不是嗎?
: 那既然繼承的子類都定義了,那麼所有的方法也都可以安心使用不是嗎@@?
: 就像前面的文章所說的
: 忍者 n = new 自來也();
: 忍者 m = new 綱手();
: n.招喚術(); // 文太出現了
: m.招喚術(); // 蝸蝓出現了
: 因為自來也、鋼手都是繼承忍者的,所以他們肯定會定義招換術,那麼程式寫成
: 自來也 n = new 自來也();
: 鋼手 m = new 綱手();
: n.招喚術(); // 文太出現了
: m.招喚術(); // 蝸蝓出現了
: 這樣也沒錯不是嗎@@?
: 拜託各位幫忙解除小弟的疑問,謝謝大家
你說的都沒錯 在這些情況下程式也的確能正確執行
但是當你要改程式的時候就不一定了
因為宣告了 綱手 m = new 綱手();
之後所有m的使用都會當成是綱手在用,而不會是當成醫療忍者在用
接著一些只有綱手有而醫療忍者沒有的function就可能被使用,比如說出現:
m.創造再生之術();
這樣的程式碼
但是當某一天你必須"修改"程式碼將醫療忍者換成別人(ex:時音)的時候:
綱手 m = new 時音(); // 不能這樣這樣寫,compile也不會過
你必須這樣寫:
時音 m = new 時音();
然後你就會發現原本寫 m.創造再生之術(); 的地方全部掛掉要重寫
已經想好的戰術都必須因為時音沒有創造再生之術()而整個改掉
一但去修改既有的邏輯(戰術) 過程中就可能產生新BUG 而且容易導致系統不穩定
但是上述的這個問題在你用 醫療忍者 m = new 綱手(); 的情況下是不存在的
因為你當初在設計戰術 是假設那是個普通的醫療忍者 而不是綱手
你不會在戰術內考慮 m.創造再生() 這件事情,你只會考慮普通醫療忍者會的招數
所以即使之後需要改變小隊配置 改為 醫療忍者 m = new 時音();
所有和 m 相關的部分都不用去改動
就算產生新BUG也一定是class 時音哪邊寫錯了 馬上就知道有問題的範圍在哪
這種將涵式介面抽像的技巧 基本上都是在為後天的修改鋪路
(這邊不考慮一些特殊技巧如command pattern / abstract factory pattern 的情況)
只要我們定義好 醫療忍者 會的東西有哪些 在使用上就可以放心使用
不需要去管管今天頂替這位置的是綱手還是時音 就算後來想換成小櫻也沒關係
你可能會問 "那我不就不能使用綱手的招數了嗎?"
這邊就會牽扯到最開始設計小隊的邏輯
你的小隊邏輯是:
一個小隊由三個忍者組成: 醫療忍者 + 隊長 + 忍者
即:
Team {
醫療忍者 m = .....
隊長 n = ......
忍者 o = ......
}
醫療忍者是誰並不重要 只要是醫療忍者就好 不用去考慮醫療忍者是不是綱手的問題
因此使用抽像的醫療忍者便足夠了 你不要去管到底那個醫療忍者是誰
這樣的情況下 你只會設計出通用的戰術 因此可以任意換上不同的醫療忍者
但如果今天我們要出的是SS級任務,必須由三忍合力組隊 你的小隊會變成這樣:
三忍Team {
綱手 m = new 綱手();
自來也 n = new 自來也();
大蛇丸 o = new 大蛇丸();
}
你在思考這個三忍Team的戰術時會直接認定這小隊的組成就是 綱手 + 自來也 + 大蛇丸
你不用去考慮由佐助頂替大蛇丸的情況 因為這隻小隊就是只能由三忍組成
這隻小隊的戰術就是為這三個人而專門設計的 換成任何人都不成立
因此這隻小隊要換別人來組的情況是不存在的 自然不用去思考換人的問題
這時候直接宣告為綱手/自來也/大蛇丸就沒有問題 因為邏輯上根本就不會有換人的情況
說了這麼多 其實就是好不好修改的問題
宣告為父類別則功能自然比較少 因為有些function只存在於子類別 比如說創造再生()
但也因為使用上有限制 換人頂替這個位置就不用擔心出狀況 因為只要是醫療忍者就ok
而如果打從一開始這位置就非得是子類別不可(比如說非綱手不可)
自然也就沒有修改的需要 因為不管改成誰都和原本的邏輯(由三忍組隊)相違背
(除非你就是想修改程式的邏輯 不過這本來就要重寫不是嗎? 因為不再是三忍Team了)
這個問題其實是所謂的耦合(coupling):
耦合度越高的程式越難修改=> 思考戰術時預設立場越多 這戰術就越少隊伍可以使用
反之耦合度越低的程式越好修改=> 這戰術只要是醫療忍者+隊長+忍者的小隊 就一定能用
最後則是
如果你的程式完全不考慮未來修改和維護的話 耦合度多高其實都沒關係XD
(但如果是開發大型程式 中間發現有bug要修改程式碼 你可能會哭出來:P)
作者: Gismudis (Gis)   2014-07-20 09:59:00
受教了
作者: jtorngl (Pedrosa go!)   2014-07-20 10:31:00
推,從override, abstract class, interface到designpattern後,就會理解為什麼要這樣設計,這篇淺顯易懂
作者: yoll522 (幽靈)   2014-07-20 19:14:00
真的受教了,這篇完全解出了我不懂的點原因在哪謝謝你的說明

Links booklink

Contact Us: admin [ a t ] ucptt.com