java - 在java中将不同的子类存储为父类是否不好

标签 java casting

将对象存储为其父类并将 object.getClass() 与预期的类进行比较以转换为子类是否被认为是不好的做法。

说明:作为基于图 block 移动的 2D 游戏的一部分,我有几种类型的“GameObject”对象,例如“Portal”、“Player”、“NPC”、“Chest”等。每个都存储在 2 维组成每个关卡的数组也充当更新和渲染队列,游戏对象体现了关卡所需的信息。 如果我将所有对象存储为父类型 GameObject 然后将它们转换为它们的实际类,例如(在 Player 类中):

private void checkPosition(x, y) {
    GameObject obj = Level.getObject(x,y);
    if(obj instanceof NPC) {
       NPC npc = (NPC)obj;
       //interact with npc
    } else if(obj instanceof Chest) {
       //handle chest
    }
}

这通常会更难阅读吗?我这样做可能会遇到什么问题?如果任何提供的每个对象都使用数组相互交互,那将是一个更好的方法,并且我将来可能会拥有其他类型的“游戏对象”,每种类型都具有根本不同的功能。

对不起,如果这有点罗嗦,因为我不确定如何解释这个问题。

edit:我应该澄清一下类似的代码可能会从 GameObject 的其他子类运行,而不仅仅是 Player(即 NPC 或更高版本的类),并且重点是能够在不更改存储的情况下更改每个子类之间的交互每次创建/更改其中一个可能存储的类类型时的级别类。感谢那些推荐 instanceof 的人我已经更新了问题以关注其他部分,但我可能会从现在开始使用它。感谢您的反馈。

结论:我决定采用 daniu 答案的变体,其中每个 GameObject 都有自己的 AI 子类,该子类扩展了上述接口(interface)的 stub /适配器。因此我不必为任何类实现 react ,我可以为相同的对象类型赋予不同的行为,并且处理交互应该如下所示:

getObject(x,y).getAI().react(obj);

最佳答案

这是访问者模式的一个用例。

添加一个界面(用于所有可能在关卡中移动的东西)

interface LevelCrawler {
   void accept(Chest chest);
   void accept(NPC npc);
}

到你的GameObject

interface GameObject { // or abstract class
    // added method
    void accept(LevelCrawler lc);  // abstract if class
}

LevelCrawler 将由例如 Player 类(或您在编辑中描述的 NPC 等)实现。

class Player implements LevelCrawler {
   public void accept(Chest chest) { ... }
   public void accept(NPC npc) { ... }
}

包含 if () {...} block 中的代码。

那么,你有例如

class Chest implements GameObject {  // I think it's a class, so probably "extends"
    void accept(LevelCrawler p) { p.handle(this); } // to call Player#handle(Chest)
}

你的代码看起来像

GameObject o = Level.getObject(x, y);
o.accept(player); // or NPC or whatever is moving right now

看,it works .

这样做的好处是,当你创建一个新的 GameObject 类时,你可以很容易地将新的行为添加到现有的 LevelCrawler 类中,并保留 checkPosition 代码不变。

Edited version PlayerNPC 在地牢中移动。

关于java - 在java中将不同的子类存储为父类是否不好,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60503928/

相关文章:

java - Spring 附加数据到当前事务

java - 在 for-each 循环中进行转换

c# - 从接口(interface)转换的 lambda 表达式

c++ - 将 vector<int> 分配给 vector<double> 安全吗?

c# - 是否有令人信服的理由反对使用 C# 关键字 "as"?

java - 发送不同对象的列表并返回其属性的总和

m2eclipse 使在 openjdk-6-jdk 上运行的 eclipse 3.5.SR2 崩溃

java - python 有类似 php java 桥的东西吗?

c# - 为什么 null 需要在这里进行显式类型转换?

java - 使用 struts2 上传文件时出现空指针异常