多类型自定义arraylist
Posted
技术标签:
【中文标题】多类型自定义arraylist【英文标题】:Multiple type custom arraylist 【发布时间】:2015-09-30 12:47:03 【问题描述】:我目前正在尝试制作一个简单的 RPG 式游戏。我希望怪物在地图上随机生成。我已经设置好了,所以当我想要一个生成它时,它会被添加到一个名为 monsters
的 ArrayList
中。当我完成时,我将拥有许多不同类型的monsters
,并且每个都有自己的类(例如 Zombie、Ghost...)每个类都有一个绘制怪物的方法,称为 draw。我想知道我该怎么做。
Monsters
是一个ArrayList<Object>
,因此它可以包含不同的类,但它不会让我这样做Monsters.get(i).draw()
;这真的可能吗,还是我很愚蠢。
【问题讨论】:
创建一个名为Monster
的接口,使用每个 怪物类型应具有的每个方法,然后将您的列表声明为List<Monster> monsters
。
它是一个类型化的 ArrayList 吗? Monster 类是否共享一个带有 draw 方法的基础 Monster 类?
如果你发布一些你的实际代码,即使它不能正常工作,也会很有帮助。
@Tom:不是 OP 写的(我在编辑 cmets 中解释过)。它被编辑了。所以我把它拿出来,以免给那些阅读 OP 以这种方式编码的问题的人留下错误的印象。我们实际上并不知道 OP 的代码是什么样的。
@Tom:啊,我明白你现在在说什么了。过失!我把它回滚了。
【参考方案1】:
您未能将对象ArrayList<Object>
投射回怪物
// Monster.get(i) == Object
// (Monster) Monsters.get(i) == Monster
// cast the list item i from Object to Monster
((Monster) Monsters.get(i)).draw();
更好的解决方案:
interface Monster
void draw();
// implement draw on each
class Zombie implements Monster
class Ghost implements Monster
ArrayList<Monster> monsters = new ArrayList<>();
// legal
monsters.add(new Zombie());
monsters.add(new Ghost());
// legal
monsters.get(i).draw();
您可以使用类 -> 扩展解决方案或此接口 -> 实现。无论哪种方式,这都是实现怪物的更好方法的一个非常简单的示例。
【讨论】:
在不需要类型转换的情况下使用接口要好得多 “您未能将对象拆箱” 这里的“拆箱”是正确的词吗? “cast”不是更正确吗,因为“unbox”更有可能将原始类型拆箱/装箱为其包装器类型? @Tom 是的,我修改了它【参考方案2】:是的,有可能,首先你需要创建一个接口,比如IMonster
,其中包含一个draw
方法。然后,让每个怪物类型实现这个接口。
您的ArrayList
将如下所示:
List<IMonster> monsters = new ArrayList<IMonster>();
monsters.add(new Ghost());
monsters.add(new Goblin());
所以这里是一个例子:
import java.util.ArrayList;
import java.util.List;
public class Monsters
private static List<IMonster> monsters = new ArrayList<IMonster>();
public static void main(String[] args)
monsters.add(new Ghost());
monsters.add(new Goblin());
monsters.add(new Devil());
for (IMonster monster : monsters)
monster.draw();
interface IMonster
public void draw();
abstract class AbstractMonster implements IMonster
@Override
public void draw()
System.out.println("Shared drawing code for all monsters");
class Ghost extends AbstractMonster
@Override
public void draw()
super.draw();
System.out.println("Ghost drawing code");
class Goblin extends AbstractMonster
@Override
public void draw()
super.draw();
System.out.println("Goblin drawing code");
class Devil extends AbstractMonster
@Override
public void draw()
super.draw();
System.out.println("Devil drawing code");
【讨论】:
不要忘记在你的语句中实际有一个变量名。 :) 并尝试始终将接口用于变量类型,因此List<IMonster>
而不是ArrayList<IMonster>
。
如果有共同的绘图代码,每个子类型可能决定先调用其超类的draw方法。子类型也可以选择完全自己绘制,在这种情况下你根本不调用 super.draw()...
@Constantin 请注意,我已将缺少的注释 @Override
添加到您的 draw
实现中。这样做总是一个很好的主意来启用编译器检查。如果您不喜欢它们,那么您或我都可以删除它们。顺便说一句:您可能需要重新考虑 new("Ghost")
,因为这不是有效的 Java 代码:P。
谢谢汤姆,我改了。我运行了代码,它似乎可以工作【参考方案3】:
你必须像这样从 ArrayList 中转换你的项目 -
Object item = Monsters.get(i);
Monster monster = (Monster) item;
monster.draw();
或者更好的是你可以使用一些接口。您可以使用接口(例如 Drawable
)。您的 Monster
和其他可绘制类将实现它。然后使用Drawable
的ArrayList
。
interface Drawable
public void draw();
public class Monster implements Drawable
public void draw()
//implementation of monster's draw
...
...
ArrayList<Drawable> monsters = new ArrayList<Drawable>();
...
...
monsters.get(i).draw();
【讨论】:
以上是关于多类型自定义arraylist的主要内容,如果未能解决你的问题,请参考以下文章
在kotlin的自定义类型arraylist中按id搜索对象[重复]