如何在 Java 中创建对象的 ArrayList 并能够访问它们的值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12022913/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to make an ArrayList of objects in Java with the ability to access their values
提问by Jeremy Sayers
so I'm working on a game in Java, and I'm a little confussed on how I should go about something. It's a Trading Card Game, kinda like Magic, and so for classes so far I have
所以我正在用 Java 开发一个游戏,我对如何去做一些事情感到有些困惑。这是一个集换式卡牌游戏,有点像万智牌,所以到目前为止我有
- GameDriver
- Cards
- WolfCard
- TheLarionCard
- 游戏驱动
- 牌
- 狼牌
- 拉里昂卡
It is my hope that I'll be able to have atleast 50 different types of card, each of which in their own class, so a little side question is, is this the best way? As for my problem:
我希望我能够拥有至少 50 种不同类型的卡片,每一种都在自己的班级中,所以一个小问题是,这是最好的方法吗?至于我的问题:
I have the following code inside my GameDriver class:
我的 GameDriver 类中有以下代码:
ArrayList<Cards> playerHand = new ArrayList<Cards>();
playerHand.add(new WolfCard());
playerHand.add(new TheLarionCard());
System.out.println(((Cards)playerHand.get(1)));
Each card extends Cards, and Cards extend GameDriver, The code above will print out something like:
每张卡片都扩展了 Cards,而 Cards 扩展了 GameDriver,上面的代码会打印出类似的内容:
TheLarionCard[panel0,0,0,0x0,invalid,layout=java.awt.FlowLayout]
But now, if I want to grab the health of say TheLarionCard, I thought I could just add .health to the last line like:
但是现在,如果我想获取 TheLarionCard 的健康状况,我想我可以将 .health 添加到最后一行,例如:
System.out.println(((Cards)playerHand.get(1).health));
But obviously I can't, what am I doing wrong here?
但显然我不能,我在这里做错了什么?
Any help is great! Thank you!
任何帮助都很棒!谢谢!
采纳答案by chm
I think you have three options:
我认为你有三个选择:
You want each different type of card to have a
health
property. In this case, you can put that property into the parent classCards
and then it will be valid to ask for the property for any class that extendsCards
. If theCards
class has ahealth
data field, the code in your question will work.You want only
TheLarionCard
to have a health property. In that case, your cast would have be:System.out.println(((TheLarionCard)playerHand.get(1).health));
This way, the compiler has knows to look in the
TheLarionCard
class for the health property, not theCards
class.You don't actually need the individual card classes to be subclasses of
Cards
. If there's no really compelling reason you've done it that way, you could have all cards be part of theCards
class and their different types (TheLarionCard, WolfCard, etc) could be designated by a data field. For example:public class Card { String type; public Card(String inType) { this.type = inType; } public String toString() { return "This is a " + type; } }
This way if you want the different cards to behave differently, you can check their
type
value and assign different behaviors based on its value, e.g.public void awesomeMethod() { if ("TheLarionCard".equals(type)) { // execute TheLarionCard code } else if ("WolfCard".equals(type)) { // execute WolfCard code } }
This is a simplified version of the Abstract Factory Patterndesign that some of the other answers were talking about, so if you're new to interfaces you could try it this way to see if the structure works, then add interfaces later.
您希望每种不同类型的卡都有一个
health
属性。在这种情况下,您可以将该属性放入父类Cards
,然后为任何扩展Cards
. 如果Cards
该类具有health
数据字段,则问题中的代码将起作用。您只想
TheLarionCard
拥有健康属性。在这种情况下,您的演员阵容将是:System.out.println(((TheLarionCard)playerHand.get(1).health));
这样,编译器就知道在
TheLarionCard
类中查找 health 属性,而不是Cards
类。您实际上并不需要将单个卡片类作为
Cards
. 如果没有真正令人信服的理由这样做,您可以让所有卡片都成为Cards
类的一部分,并且它们的不同类型(TheLarionCard、WolfCard 等)可以由数据字段指定。例如:public class Card { String type; public Card(String inType) { this.type = inType; } public String toString() { return "This is a " + type; } }
这样,如果您希望不同的卡片表现不同,您可以检查它们的
type
值并根据其值分配不同的行为,例如public void awesomeMethod() { if ("TheLarionCard".equals(type)) { // execute TheLarionCard code } else if ("WolfCard".equals(type)) { // execute WolfCard code } }
这是其他一些答案所讨论的抽象工厂模式设计的简化版本,因此如果您不熟悉接口,您可以尝试这种方式,看看结构是否有效,然后再添加接口。
回答by Jo?o Silva
Define an interface or abstract method getHealth()
method in Cards
, that must be implemented by WolfCard
and TheLarionCard
. Then, you can do playerHand.get(1).getHealth()
.
在 中定义接口或抽象方法getHealth()
方法Cards
,必须由WolfCard
和实现TheLarionCard
。然后,你可以做playerHand.get(1).getHealth()
。
For instance:
例如:
public abstract class BaseCard {
protected int health;
public abstract int getHealth();
}
public class WolfCard extends BaseCard {
private int wolfHealthBoost;
public int getHealth() {
return health + wolfHealthBoost;
}
}
public class TheLarionCard extends BaseCard {
public int getHealth() {
return health;
}
}
回答by Rolobster
You should check if you have the getter for the health attribute in those classes, private attributes can't be accessed from outside the class.
您应该检查这些类中是否有 health 属性的 getter,不能从类外部访问私有属性。
Just make a new method, getHealth(), that returns the health attribute, and then append it after the dot at the last line.
只需创建一个新方法 getHealth(),它返回 health 属性,然后将其附加在最后一行的点之后。
BTW, you don't have to cast the Cards class if you already defined the ArrayList with that stereotype.
顺便说一句,如果您已经使用该构造型定义了 ArrayList,则不必强制转换 Cards 类。
回答by Shivan Dragon
You don't really need interfaces or even such a complex variety of classes. I'm guessing all of your Cards have generally similar behavior. They are of a certain type, can do a specific action, can have actions and/or effects happen onto them etc. So you only need one Cards class for this, and in it have all the fields and methods that manage those generic states/actions.
您实际上并不需要接口,甚至不需要如此复杂的各种类。我猜你所有的卡片都有大致相似的行为。它们属于某种类型,可以执行特定操作,可以对它们执行操作和/或效果等。因此,您只需要一个 Cards 类,其中包含管理这些通用状态的所有字段和方法/行动。
Then you can make separate classes that inherit from Cards class (which btw, it's better to rename to just "Card"), like if you have effect type cards (such as a MTG Mana Flare or Hideous Visage equivalents) and then you also have creature cards (like MTG's Shivan Dragon or Dragon Whelp) you can make classes such as EffectCard which might have it's own fields like "duration" and "affectedTypes" and then use it to make ManFlare instances, Hideous Visage instances, etc. Also make a CreatureCard with stuff like hitpoints, firstStrike, etc. and make ShivanDragon instances and DragonWhelp instances from it.
然后,您可以创建从 Cards 类继承的单独类(顺便说一句,最好重命名为“Card”),例如如果您有效果类型的卡片(例如 MTG Mana Flare 或 Hideous Visage 等价物),那么您还有生物卡(例如 MTG 的 Shivan Dragon 或 Dragon Whelp),您可以制作诸如 EffectCard 之类的类,这些类可能具有自己的字段,例如“duration”和“affectedTypes”,然后使用它来制作 ManFlare 实例、Hideeous Visage 实例等。还可以制作一个CreatureCard 包含生命值、firstStrike 等内容,并从中制作 ShivanDragon 实例和 DragonWhelp 实例。
Also don't be afraid of composition. Instead of subclassing/making extra classes for each card, make a simpler hierarchy like the one above and pass it "command" or "action" classes which dictates the more specific details. Like the FirstStrike instance of the EffectCard class could be initialized with an "action" instance that tells it specifically how to affect a CreatureCard instance, the ShivanDragon instance of the CreatureCard class would have an action telling it how it's attack can be increased by utilizing Red Lands cards, etc.
也不要害怕作文。不是为每张卡片子类化/创建额外的类,而是创建一个更简单的层次结构,如上面的层次结构,并将其传递给“命令”或“动作”类,这些类指示更具体的细节。就像 EffectCard 类的 FirstStrike 实例可以用一个“动作”实例初始化,具体告诉它如何影响 CreatureCard 实例,CreatureCard 类的 ShivanDragon 实例将有一个动作,告诉它如何通过使用 Red 来增加攻击地牌等