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