简体   繁体   English

子类和超类方法

[英]Subclass and Superclass methods

I'm creating a monopoly game with different types of squares. 我正在创建具有不同类型正方形的垄断游戏。 Square is the Superclass and PropertySquare is the Subclass . Square父类PropertySquare子类

I've created a loop that rolls the dice and moves the players to a different square. 我创建了一个循环,掷骰子并将玩家移到另一个正方形。 The squares are in an array list and I am able to call the superclass methods on them. 这些正方形在数组列表中,我可以在它们上调用超类方法。 However, even if the squares are set to more specific types (subclass of square), I cannot call the subclass methods on them. 但是,即使将正方形设置为更特定的类型(正方形的子类),我也无法在它们上调用子类方法。

This is how I have initialised the squares in a board 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 is a method in the superclass square. getName是超类正方形中的方法。 However, even if the square is a property type, I cannot call the methods in the PropertySquare class such as getPrice(); 但是,即使正方形是属性类型,也无法调用PropertySquare类中的方法,例如getPrice();

How would I change this or be able to call the subclass methods? 我将如何更改它或能够调用子类方法?

I assume board.getSquare() returns a Square , and Square doesn't have any getPrice() method, so you can't call getPrice() over an object declared as Square , even if the instance is actually a PropertySquare (aka polymorphism ). 我假设board.getSquare()返回一个Square ,而Square没有任何getPrice()方法,因此即使实例实际上是一个PropertySquare (aka 多态性 getPrice() ,也不能在声明为Square的对象上调用getPrice() )。 To do so, you have to first cast to the specific subclass. 为此,您必须首先转换为特定的子类。 For example: 例如:

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

NB: I'm going to answer this in the more generic sense, I realise that not all Monopoly Squares have a price... But the problem itself, in code, can be solved in two ways. NB:我要从更一般的意义上回答这个问题,我意识到并不是所有的垄断广场都有价格……但是,代码本身的问题可以通过两种方式解决。

If all of your items have a price, you probably want to use an "Abstract" base class. 如果所有商品都有价格,则可能要使用“抽象”基类。

You then put in the methods in the superclass as 然后,您将超类中的方法放入:

protected abstract int getPrice();

and implement it in your subclass. 并在您的子类中实现它。

So you could have subclasses such as undevelopedSquare, propertySquare, gardenSquare etc. 因此,您可能拥有诸如undevelopedSquare,propertySquare,gardenSquare等子类。

However, in the case of Monopoly, if only the propertySquare instances have getPrice, you should use 但是,对于Monopoly,如果只有propertySquare实例具有getPrice,则应使用

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

NB2: You also have "utilitySquare"s such as the Waterworks, which would have different properties alongside the price (you can't build a hotel on a utility even though you can buy it). NB2:您还拥有“公用事业广场”,例如Waterworks,它的价格旁边会有不同的属性(即使您可以购买,也无法在公用事业上建造酒店)。

So in this case, maybe Interfaces would be more appropriate such as: 因此,在这种情况下,接口可能更合适,例如:

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

interface SaleableSquare -> has pricing etc

interface BuildableSquare -> can build hotels

And then have your generic as 然后将您的通用

private static final ArrayList<? extends Square> squares

The PropertySquare would then be: 然后,PropertySquare将是:

public class PropertySquare extends AbstractSquare implements SaleableSquare, BuildableSquare

where the Abstract class implements "PlayableSquare". 其中Abstract类实现了“ PlayableSquare”。 Although that may be a step too far as it would almost just be a marker interface. 尽管那可能只是一步,因为它几乎只是标记界面。

you can use instanceOf to check for each interface implementation, ie if a Utility has a different method you wish to call. 您可以使用instanceOf来检查每个接口的实现,即,某个Utility是否具有您希望调用的其他方法。

You should use Generics with the ArrayList. 您应该将泛型与ArrayList一起使用。 If your list only contains of type PropertySquare , do it like this: 如果您的列表仅包含PropertySquare类型,请执行以下操作:

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

Then the list will returns objects of type PropertySquare . 然后,列表将返回PropertySquare类型的对象。

If the list can contain any type of square, do it like this: 如果列表可以包含任何类型的正方形,请执行以下操作:

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
}

The problem in your code is that your object is of type Square and does not know anything about the methods of any subclass. 您的代码中的问题是您的对象属于Square类型,并且对任何子类的方法一无所知。 So you have to do a type cast. 因此,您必须进行类型转换。

you could handle the landing square in a group of ifs like: 您可以通过一组ifs处理着陆广场:

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

Your declared ArrayList is bound to Square meaning you will have a collection of Square objects and a Square reference when interacting with any items despite at run-time it being an instance of a subclass. 您声明的ArrayList绑定到Square这意味着在与任何项目进行交互时,尽管它是子类的实例,但您将拥有Square对象的集合和Square引用。 This is known as polymorphism. 这称为多态性。

Due to the fact that the references are of type Square the only methods Java knows about are those declared in Square and any other inherited methods. 由于引用是Square类型的事实,因此Java知道的唯一方法是那些在Square声明的方法以及任何其他继承的方法。 For you to be able to call methods of a subclass you would need to check whether the reference is pointing to an instance of PropertySquare and then down-cast the reference to PropertySquare . 为了能够调用子类的方法,您需要检查引用是否指向PropertySquare的实例,然后将引用向下转换PropertySquare You're then saying, it's okay I know its an instance of PropertySquare so I can safely call the getPrice() method declared in PropertySquare . 您是说,没关系,我知道它是PropertySquare一个实例,因此我可以安全地调用PropertySquare声明的getPrice()方法。

if (square instanceof PropertySquare) {
    ((PropertySquare)square).getPrice();
}

Alternatively you can look at the instances class name: 或者,您可以查看实例的类名称:

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

For more info: 有关更多信息:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM