作者Killercat (殺人貓™)
看板java
標題Re: [問題] is-a 關係在Java程式的時候的用意?
時間Thu Aug 1 11:39:53 2013
※ 引述《SamLucien (黑)》之銘言:
: 我用Java SE技術手冊 良葛格 這本想提問題
: (第六章 6-7頁)
: 一個遊戲 腳色(Role)類別
: 劍士(SwordsMan)、魔法師(Magician) 則是繼承了 Role類別的所有基本腳色該有的東西
: 也就是 SwordsMan is-a Role , Magician is-a Role
: 通常在Java 看到的實作劍士(SwordsMan)、魔法師(Magician)
: 通常都會這樣寫:(1)
: SwordsMan role1 = new SwordsMan();
: Magician role2 = new Magician();
: 但是,通常也會看到這樣寫:(2)
: Role role1 = new SwordsMan();
: Role role2 = new Magician();
: 我想請問的是這兩種寫法有什麼差別?
: 因為現在遇到看不懂的地方也包含
: 就我的認知是應該這樣寫
: ArrayList<Map<String,Object>> list
: = new ArrayList<Map<String,Object>>();
: 但是看到這 就不知道為什麼 可以這樣寫 用意何在?
: List<Map<String,Object>> list
: = new ArrayList<Map<String,Object>>();
: 就是想問說(1)與(2) 這樣的寫法 有什麼差別呢???
: (2) 的寫法有什麼用意???
: 謝謝大家~
不過現在的主流做法並不是繼承class。
繼承class(後面會提到擴展interface)一定是正確的,但是現在基本上已經不流行這套
因為它會造成一些問題,尤其是java並不允許多重繼承,會造成很多設計上的困難
我先舉個例子,我們傳統的寫法可能會寫成這樣
interface IRole {
int getHP();
int getMP();
int getEXP();
}
class Role implements IRole {
int HP;
int MP;
int EXP;
bool kill(IRole target);
bool kiss(IRole target);
bool kick(IRole target);
}
class Swordman extends RoleBase {
bool somethingSwordmanOnly(IRole target);
}
IRole a = new Swordman();
IRole b = new Magician();
可能差一點的coder連IRole那層都沒有, 直接就
Role a = new Swordman();
whatever,這是舉例,大家都知道的
現在的主流分為以下幾種
1. 繼承interface而非class
interface IRole {
int getHP();
int getMP();
int getEXP();
boolean kill(IRole target);
boolean kiss(IRole target);
boolean kick(IRole target);
}
interface ISwordman extends IRole {
int getSomethingSwordmanOnly();
boolean doSomethingSwordmanOnly(IRole target);
}
class Swordman implements ISwordman {
}
這樣做有幾個好處,首先最顯而易見的好處就是Swordman避開了繼承的問題
改成實作。繼承只能繼承一個,但實作可以實作很多很多個
用法也完全一樣
IRole role = new Swordman();
但是這樣也是有缺點的:你可以想像終端class(也就是最後implements的class)
會有多肥大 =P 而且...
2. 使用inner implementation
interface IRoleStat {
//getHP, MP, EXP...同上
}
interface IAction {
//角色共通的行為, 比方說target(), kill(), attack()....etc
}
interface ISwordmanStat extends IRoleStat {
//定義Swordman才有的property
}
interface ISwordmanAction extends IAction {
}
class Role {
IRoleStat charStat;
IAction charAction;
}
可能當你想創造一個戰士的時候
Role role = new Role(new SwordmanStat(), new SwordmanAction());...
當然,大家都懂design pattern,這個可以用Factory來做 XD
這樣做還有一個好處,比方說有個敵人特色是會分身,HP會共享
Role enemy = context.getEnemy();
分身後
Role doppelganger = new Enemy();
doppelganger.setCharStat(enemy.getCharStat());
現在不管你打誰兩邊血量都會一起扣了,連delegate都不用 XD
這只是剛好遊戲可以拿這個當例子啦...
3. 很類似2 但是把所有東西轉成JSON(或者任何你能解析的格式)
class Role {
String actionProperty;
String statProperty;
}
這種寫法其實出乎意料的多專案使用(不管java, ios...)
他的相依性是最低的,甚至有人替他寫出高效能的property實作
class Role {
SuperRockProperty actionProperty;
SuperRockProperty statProperty;
}
缺點當然明顯,就是沒有形別安全根檢查。不過會這樣寫的大概也不在乎這個了...
更狠一點的話會變成這樣
class Role {
SuperRockProperty property;
}
連分類都省了....
除了繼承以外,我相信1 2都是可以參考的新的實作風法。
Spring也有類似DI等等的低相依class injection方法,這些也可以參考一下
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 59.124.251.135
推 PsMonkey:一開始的 IRole 少了 abstract? 08/01 11:52
→ PsMonkey:還是你寫得根本不是 Java(bool????) 08/01 11:52
改一下你說的部分
不過IRole本來就不用abstract阿 他是interface XD
一個常常得寫四種語言的人 bool boolean不分是很合理地(快逃)
※ 編輯: Killercat 來自: 59.124.251.135 (08/01 11:59)
→ Killercat:噢你說的abstract指的是沒function 那只是懶得寫getter 08/01 12:00
不過想了一想PS猴說得有道理 還是補上去好了....
※ 編輯: Killercat 來自: 59.124.251.135 (08/01 12:17)
※ 編輯: Killercat 來自: 59.124.251.135 (08/01 13:11)
推 PsMonkey:沒內容的 method 沒有 abstract 修飾感覺很奇怪阿 Orz 08/01 13:28
推 popcorny:有點overengineering..有時候架構夠用就好 不要太複雜 08/01 13:34
→ Killercat:這算是我目前看過常見的實作法 而非要這樣設計 08/01 13:35
推 popcorny:1像是bridge pattern, 2像是delegate pattern.. 08/01 13:44
→ Killercat:其實這些概念統稱composite :) 08/01 13:59
→ Killercat:另外3的概念其實就是javascript來的... 我覺得頗畸形 08/01 14:01