Re: [問題] is-a 關係在Java程式的時候的用意?

看板java作者 (殺人貓™)時間12年前 (2013/08/01 11:39), 編輯推噓4(405)
留言9則, 3人參與, 最新討論串2/3 (看更多)
※ 引述《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
一開始的 IRole 少了 abstract?
08/01 11:52, 1F

08/01 11:52, , 2F
還是你寫得根本不是 Java(bool????)
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
噢你說的abstract指的是沒function 那只是懶得寫getter
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
沒內容的 method 沒有 abstract 修飾感覺很奇怪阿 Orz
08/01 13:28, 4F

08/01 13:34, , 5F
有點overengineering..有時候架構夠用就好 不要太複雜
08/01 13:34, 5F

08/01 13:35, , 6F
這算是我目前看過常見的實作法 而非要這樣設計
08/01 13:35, 6F

08/01 13:44, , 7F
1像是bridge pattern, 2像是delegate pattern..
08/01 13:44, 7F

08/01 13:59, , 8F
其實這些概念統稱composite :)
08/01 13:59, 8F

08/01 14:01, , 9F
另外3的概念其實就是javascript來的... 我覺得頗畸形
08/01 14:01, 9F
文章代碼(AID): #1H-TYC6n (java)
文章代碼(AID): #1H-TYC6n (java)