Re: [問題] is-a 關係在Java程式的時候的用意?
※ 引述《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
推
08/01 11:52, , 1F
08/01 11:52, 1F
→
08/01 11:52, , 2F
08/01 11:52, 2F
改一下你說的部分
不過IRole本來就不用abstract阿 他是interface XD
一個常常得寫四種語言的人 bool boolean不分是很合理地(快逃)
※ 編輯: Killercat 來自: 59.124.251.135 (08/01 11:59)
→
08/01 12:00, , 3F
08/01 12:00, 3F
不過想了一想PS猴說得有道理 還是補上去好了....
※ 編輯: Killercat 來自: 59.124.251.135 (08/01 12:17)
※ 編輯: Killercat 來自: 59.124.251.135 (08/01 13:11)
推
08/01 13:28, , 4F
08/01 13:28, 4F
推
08/01 13:34, , 5F
08/01 13:34, 5F
→
08/01 13:35, , 6F
08/01 13:35, 6F
推
08/01 13:44, , 7F
08/01 13:44, 7F
→
08/01 13:59, , 8F
08/01 13:59, 8F
→
08/01 14:01, , 9F
08/01 14:01, 9F
討論串 (同標題文章)
本文引述了以下文章的的內容:
完整討論串 (本文為第 2 之 3 篇):