【问题标题】:Proper Java inheritance structure正确的 Java 继承结构
【发布时间】:2014-07-14 02:09:28
【问题描述】:

我正在用 Java 编写一个 2048 游戏和自解算器。我最重要的类是Board,它包含主要的游戏功能。出于效率原因,游戏的许多方面都编码在数组中,例如向左或向右移动时每个可能行的转换。在static 初始化块中,我调用static void generateTables(),它会创建一次表。

具有求解能力的板 extend Boardimplement Solver,一个包含高级方法 getDirection()getWorstLocation() 的接口,接口类使用这些方法运行求解器并获取提示.我感兴趣的主要求解器类型记录所有可能行的启发式值列表,然后使用这些值运行 expectiminimax 搜索。所以我有课:

public class HeuristicBoard extends Board implements Solver {

    private static int[] heuristic; // Lookup table

    /* ... methods omitted ... */

    private int heuristic() {...}
    // Calculates a heuristic value for the entire board based
    // on calls to the following method
    // This method's code could change depending on algorithm implementation.
    private static int heuristic(short row) {...}
    // Checks the lookup table for the row provided
    private static void generateHeuristicTable() {...}
    // Generates the lookup table based on calls to the following method
    private static int heuristic(byte[] row) {...}
    // Calculates the heuristic value for a single row.
    // This method's code could change depending on algorithm implementation.
}

现在,我想测试多个不同的启发式算法,但使用相同的 expectiminimax 算法。因此,int heuristic()static int heuristic(byte[] row) 的实现会发生变化,而其他的将保持不变。抽象HeuristicBoard 类的功能以便拥有多个实现int heuristic()static int heuristic(byte[] row) 的子(?)类的最佳方法是什么?最好他们有一个共同的祖先,这样我就可以拥有:

ClassOrInterface firstSolver = new EmptySpaceHeuristicBoard();
ClassOrInterface secondSolver = new MonotonicityHeuristicBoard();

我在各种 StackOverflow 答案中的想法和看到的建议:

  1. 制作HeuristicBoardabstract和制作两个方法abstract。但是由于某种原因(是的,我已经阅读了原因)您不能使用static abstract 方法。如果我使static int heuristic(byte[] row) 非静态,我将无法在static void generateHeuristicTable() 方法中使用它,它应该在HeuristicBoard 类中实现,而不是在子类中(我必须在每个子类,每次只更改一次性的new SubclassOfHeuristicBoard().heuristic(currentRow)。如果我也将此方法设为非静态方法,忽略上面展示的不便,那么我将无法在static初始化块中调用generateHeuristicTable(),从而使以便类的每个新实例都会生成(大)表。

  2. 创建一个包含静态方法的HeuristicSolver接口,然后有HeuristicBoardimplementHeuristicSolver,然后是HeuristicBoard的子类。但是,这迫使我提供静态方法的默认实现,我认为这没有意义。只有子类应该被实例化,因为只有它们应该提供启发式实现。此外,类中的其他静态方法引用的静态变量只能在Board 类中找到。

  3. 还有其他可能性,但在使 HeuristicBoard 非抽象之后,它们真的会变得更糟。

在我看来,唯一正确的方法是创建HeuristicBoard abstract,但我不知道如何使用static 方法。

编辑:已经指出这两种方法都可以更改为non-static。这样就解决了上面的问题,但是现在我又遇到了一个问题:在非静态AI方法中,为了递归的目的,我复制了板子:HeuristicBoard option = new HeuristicBoard(board)。但是,如果类是抽象的,我就不能这样做。我应该如何创建当前类的实例? (即在EmptySpaceHeuristicBoard类中,当这个方法被继承并执行时,它应该创建一个new EmptySpaceHeuristicBoard()

【问题讨论】:

  • 对于初学者来说,我认为使用静态初始化器是一个糟糕的设计。只需检查表是否为null

标签: java oop inheritance static abstract


【解决方案1】:

几个观察:

  1. 静态方法始终可以实现为不使用任何实例变量的实例方法,因此应该可以解决您无法覆盖静态方法的问题。

  2. 我不明白为什么启发式板正在扩展板。我认为让 Solver 类具有像 scoreBoard() 这样的方法更有意义。

  3. 2048 不是极小极大游戏,因为“对手”没有选择“最小”选项,而是随机选项。因此要使用的优化器是 expectimax。

【讨论】:

  • 我使用 expectimax 来寻找可能的最佳移动,并使用 minimax 来寻找最差的瓷砖位置,具体取决于模式。我误导了优化器,哎呀。
  • 另外:将静态方法变成没有实例变量的实例方法不是坏习惯吗?这不是破坏了静态方法的全部目的吗?
  • 能够覆盖该方法是不使其成为静态的一个很好的理由。
猜你喜欢
  • 2019-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-13
相关资源
最近更新 更多