子类和超类方法

Subclass and Superclass methods

我正在创建一个具有不同类型方块的垄断游戏。 SquareSuperclassPropertySquareSubclass

我创建了一个循环,可以掷骰子并将玩家移动到不同的方块。这些方块在一个数组列表中,我可以对它们调用 superclass 方法。但是,即使将正方形设置为更具体的类型(正方形的 subclass),我也无法对它们调用 subclass 方法。

这就是我在棋盘中初始化方块的方式 class。

private static final ArrayList<Square> squares = new ArrayList<Square>(40);
squares.add(1, new PropertySquare("Old Kent Road", 1, 60, "Brown"));
board.getSquare(pos).getName());

getName是superclass方中的一个方法。但是,即使正方形是属性类型,我也无法调用PropertySquareclass中的方法,例如getPrice();

我该如何更改它或如何调用 subclass 方法?

我假设 board.getSquare() returns 一个 Square,而 Square 没有任何 getPrice() 方法,所以你不能调用 getPrice() 覆盖声明为 Square 的对象,即使实例实际上是 PropertySquare (a.k.a. polymorphism)。为此,您必须首先转换为特定的子类。例如:

final Square square = board.getSquare(pos);
if (square instanceof PropertySquare) {
    ((PropertySquare)square).getPrice();
}

注意:我将从更一般的意义上回答这个问题,我意识到并非所有的垄断方块都有价格……但是问题本身,在代码中,可以通过两种方式解决。

如果您的所有商品都有价格,您可能希望使用 "Abstract" 基础 class。

然后你把方法放在 superclass as

protected abstract int getPrice();

并在你的子程序中实现它class。

因此您可以拥有子classes,例如 undevelopedSquare、propertySquare、gardenSquare 等

然而,在大富翁的情况下,如果只有propertySquare实例有getPrice,你应该使用

if (square instanceOf PropertySquare) {
    price = ((PropertySquare)square).getPrice();
}

NB2:您还有 "utilitySquare"s,例如 Waterworks,它们除了价格之外还有不同的属性(即使您可以购买,也不能在公用设施上建造酒店)。

所以在这种情况下,也许接口会更合适,例如:

interface PlayableSquare -> Generic square things, you can land on one for instance

interface SaleableSquare -> has pricing etc

interface BuildableSquare -> can build hotels

然后让你的泛型成为

private static final ArrayList<? extends Square> squares

PropertySquare 将是:

public class PropertySquare extends AbstractSquare implements SaleableSquare, BuildableSquare

摘要 class 实现 "PlayableSquare"。尽管这可能有点过分,因为它几乎只是一个标记界面。

您可以使用 instanceOf 来检查每个接口的实现,即如果 Utility 具有您希望调用的不同方法。

您应该将泛型与 ArrayList 一起使用。 如果您的列表只包含 PropertySquare 类型,请这样做:

private static final ArrayList<PropertySquare> squares = new ArrayList<>(40);
squares.add(1, new PropertySquare("Old Kent Road", 1, 60, "Brown"));

然后列表将 returns 个类型为 PropertySquare 的对象。

如果列表可以包含任何类型的正方形,请这样做:

private static final ArrayList<Square> squares = new ArrayList<>(40);
squares.add(1, new PropertySquare("Old Kent Road", 1, 60, "Brown"));
Square sq = squares.get(0);
if(sq instanceof PropertySquare){
    PropertySquare pSq = (PropertySquare) sq;
    //now you can use any method of PropertySquare
}

您的代码中的问题是您的对象是 Square 类型,并且不知道任何子类的方法。所以你必须做一个类型转换。

您可以在一组 ifs 中处理着陆广场,例如:

if (square instanceof PropertySquare) {
    ((PropertySquare)square).getPrice();
}else if(square instanceof PrisonSquare) {
//do nothing 
}//etc..

您声明的 ArrayList 绑定到 Square 意味着您将拥有 Square 对象的集合和 Square 与任何项目交互时的引用,尽管在 运行-时间它是一个子实例class。这称为多态性。

由于引用的类型是 Square,因此 Java 知道的唯一方法是那些在 Square 中声明的方法和任何其他继承的方法。为了能够调用 subclass 的方法,您需要检查引用是否指向 PropertySquare 的实例,然后 down-castPropertySquare 的引用。然后你说,没关系,我知道它是 PropertySquare 的一个实例,所以我可以安全地调用 PropertySquare.

中声明的 getPrice() 方法
if (square instanceof PropertySquare) {
    ((PropertySquare)square).getPrice();
}

或者您可以查看实例 class 名称:

square.getClass().getSimpleName();  // Would just give you PropertySquare
square.getClass().getCanonicalName(); // Would give you the fully qualified name e.g. com.foo.bar.PropertySquare

更多信息:

https://docs.oracle.com/javase/tutorial/java/IandI/polymorphism.html