【问题标题】:Java create instances of classes on the flyJava 动态创建类的实例
【发布时间】:2015-07-17 12:48:11
【问题描述】:

我正在制作一个小型纸牌游戏。在这个游戏中,新玩家是一个类的实例,AIPlayer 或 HumanPlayer,它扩展了一个通用玩家类。

目前要生成播放器,我有以下代码:

private List<Player> players;

HumanPlayer playerA = new HumanPlayer("playerA");
playerA.addObserver(gameModelObserver);
players.add(playerA);

AIPlayer playerB = new AIPlayer("playerB");
playerB.addObserver(gameModelObserver);
players.add(playerB);

AIPlayer playerC = new AIPlayer("playerC");
playerC.addObserver(gameModelObserver);
players.add(playerC);

HumanPlayer playerD = new HumanPlayer("playerD");
playerD.addObserver(gameModelObserver);
players.add(playerD);

是否可以动态生成这些类? 我可以做一些事情,比如用玩家姓名和布尔值遍历链表的所有元素,以指示他们是 AI 还是 Human,然后为他们生成一个类的实例。如果有,怎么做?

编辑:为了更清楚,我正在寻找这样的事情是否可能:

for(int i=0; i<x; i++){
player i = new Player("i");
i.addObserver(gameModelObserver);
players.add(i); }

【问题讨论】:

  • 动态生成这些类是什么意思?您可以通过instanceof 检查List&lt;Player&gt; 中的实际对象并做出相应的反应,但这(至少从我的角度来看)是一个不雅的解决方案。为什么您需要知道PlayerAIPlayer 还是HumanPlayer?也许你的设计有缺陷。
  • 创建一个方法addPlayer(String name)
  • AIPlayer 和 HumanPlayer 有不同的功能。我也觉得这很奇怪,但我想知道这是否可能。
  • @Turing85 为什么不违法,工厂模式 v.1 是合法的。
  • @HansvanderLaan 也许这就是问题所在。从抽象的角度来看,AIPlayerHumanPlayer 应该具有相同的(基本)功能(例如一些makeMove-方法)。对于游戏来说,它应该是完全透明的,是人工智能还是人类在移动。

标签: java class


【解决方案1】:

这不能回答你的问题,但是,也许可以解决你的问题:

private List<Player> players;

public void createPlayerByName(String name, Class type) {
  Player player = type.equals(HumanPlayer) ? new HumanPlayer(name) : new IAPlayer(name);
  player.addObserver(gameModelObserver);
  players.add(player);
}

public void createHumanPlayerByName(String name) {
  createPlayerByName(name, HumanPlayer.class);
}

public void createIAPlayerByName(String name) {
  createPlayerByName(name, AIPlayer.class);
}

所以你只需要这样做:

for (String name : humanNameList) {
  createHumanPlayerByName(name);
}

for (String name : aiNameList) {
  createAIPlayerByName(name);
}

【讨论】:

  • 谢谢。它可以通过这种方式解决我的问题。我仍然很好奇我所问的是否可行 :)
  • 可以但不推荐使用Player player = AIPlayer.class.newInstance();创建,因为它不会调用构造函数,只生成Object。
  • @Sertage "[...] 因为它不会调用构造函数。" 在 Java 中,如果不调用构造函数就无法创建对象。 Javadoc for newInstance() 明确表示“[...] 该方法传播由 nullary 构造函数 引发的任何异常,包括已检查异常”(通过反射调用) .但是,最好使用Constructors.newInstance(Object ...)
  • @Turing85 对不起,你是对的。我对它的工作原理有不同的想法。谢谢:)
【解决方案2】:

大概是这样的:

class Player {

    String name;
    Type type;

    public Player(String name, Type type) {
        this.name = name;
        this.type = type;
    }
}

Player[] playersList = { new Player("playerA", Type.HUMAN), new Player("playerB", Type.AI)};
for (Player player: playersList) {
    if (player.type == Type.AI) {
            AIPlayer aiPlayer = AIPlayer.class.getConstructor(String.class).newInstance(player.name);
            aiPlayer.addObserver(gameModelObserver);
            players.add(aiPlayer);                                    }
    else {
            HumanPlayer humanPlayer = HumanPlayer.class.getConstructor(String.class).newInstance(player.name);
            humanPlayer.addObserver(gameModelObserver);
            players.add(humanPlayer);
    }

}

【讨论】:

  • 如果您已经调用了属性playerList,为什么还要使用数组而不是List?此外,在 OP 中有两个以上的玩家。
  • 感谢您的解决方案。在您建议的代码中,我将如何向新生成的播放器添加一个观察者?这是我面临的主要问题。
  • 只需将addObserver方法放在循环中的if下方即可。
  • @Turing85 你对命名是正确的:我注意到在我编写代码后 OP 使用了一个名为“players”的变量,所以我在没有注意到不一致的情况下即时重命名它。对于玩家,我认为 OP 可以做一些复制和粘贴.. :-)
猜你喜欢
  • 2015-12-17
  • 2017-08-20
  • 1970-01-01
  • 2020-05-11
  • 1970-01-01
  • 1970-01-01
  • 2020-06-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多