Accessing subclass method from other class - java

so I'm making a card game.
I have an arrayList of type player in my main, and I have filled it with a certain type of player (in this case, a good player - good player being a subclass of player with a couple of additional methods)
I may just be brain dead from looking at this for too long however heres my code.
I create 4 good players - again - goodPlayer extends player
ArrayList<Player> players = new ArrayList<>();
for (int i = 0; i < 4; i++)
{
goodPlayer gp = new goodPlayer();
players.add(gp);
}
Then after a couple of methods are called I want to call a method from goodPlayer called count, on each of the goodPlayers in players arrayList
for (Player p : players)
{
count(p.getHand());
}
what am I doing wrong as what I currently have is incorrect, unless I make count static and call goodPlayer.count however I do not want the class to act in a static context.
Thanks.

Why don't you use type casting? You don't need to make count method a static one to use it. If you are 100% sure that all players in that list will be from GoodPlayer class (by convention, class names start with a capital), then just cast it as
((GoodPlayer) player).count();
If you're not sure if all players will be from the class GoodPlayer, then add a test to avoid a runtime error:
if (player instanceof GoodPlayer) {
((GoodPlayer) player).count();
}

A solution would be to add a method on your abstract player class and implement that differently in your derived types of player. For example:
public abstract class Player
{
public abstract int count();
}
public class GoodPlayer extends Player
{
public int count()
{
return totalHandsPlayed * 3; //Or something meaningful;
}
}
This example is showing the you have a base class that asks any inherited classes to implement the methods defined as abstract. (in this case count).

If your players list is always going to hold GoodPlayer objects, then it would be best to have it as a a list of GoodPlayers
Otherwise, the answer given by user mehmetakcay best suits your purpose.

though the information you have provided seems to be little bit abstract but you can do in following manner (using downcasting, though its not recommended):
for(Player p:players){
GoodPlayer gp=(GoodPlayer)p;
gp.count();
}

Related

How can I call a method on an object that is stored in a polymorphic array in Java?

Hi and thanks for taking time to look at my problem.
I am trying to call a method on an object held in an object array.
There are three classes: Cards, Guard and Deck.
The Guard class extends the Cards class.
The array is of type 'Cards' and is instantiated in the Deck class.
The Cards class is pretty much empty:
public class Cards {
}
The object being stored in the array is of type Guard. Here is the Guard class and it's state and methods:
public class Guard extends Cards{
private int cardScore = 2;
private String cardName = "Guard";
private String cardAbility = "this is the guard's ability";
public void printGuardInfo()
{
System.out.println("This card score fo the guard is: "+cardScore);
System.out.println("The card name is: "+ cardName);
System.out.println("The card ability is" + cardAbility);
}
}
I am instantiating the array in the Deck class. I am then filling a array of type Cards with objects of type Guard.This is polymorphism, I believe.
This works and I can print the reference variables held at each index point.
public class Deck {
Cards[] deck = new Cards[16];
public Cards[] getDeck() {
return deck;
}
public void addGuards()
{
for(int i=0; i<5; i++)
{
deck[i] = new Guard();
deck[i].printGuardInfo();// Error: cannot resolve method printGuardInfo()
}
}
}
My problem is that I now cannot call the printGuardInfo() method on deck[i].
I have searched and googled for a while now but with no success. I feel like I need an interface, or abstract class of some sort. Unfortunately I am not knowledgeable enough in these areas.
Any help at all is much appreciated, Thank you.
I´d promote something like this:
Make Cards an interface
public interface Cards {
void print();
}
Make Guard implement this interface and override the print method there with the needed information.
public class Guard implements Cards{
// ... Other methods and stuff
#Override
public void print() {
System.out.println("This card score fo the guard is: "+cardScore);
System.out.println("The card name is: "+ cardName);
System.out.println("The card ability is" + cardAbility);
}
// ... Other methods and stuff
}
Now in the loop you just have to call
deck[i].print();
What is getting printed now will be depending on the actual implementation of what has to be printed, but in generall the class Cards will know that it can print now.
Edit: Following #chrylis comment, your class should be called Card instead of Cards. The reason here? It´s like a simple plan for a single type of Card(class here), but doesn´t represent multiple Cards(multiple cards would be instances of Card).
While some of the proposed solutions make sense in the narrow case (using a combination of instanceof and casting the impacted Cards element to Guard in order to invoke printGuardInfo), there might be a broader problem with the design of your inheritance.
Assuming Cards is not really an empty class (otherwise the hierarchy does really not produce any benefit), my advice is to group your card objects under a common interface or abstract class (say, Card), and have that interface provide an abstraction for general methods such as printInfo, which is then implemented by each Card type (you'd get the printGuardInfo code inside the Guard implementation there).
In turn, when iterating your array, you'd invoke printInfo on each card, knowing that each and every child of Card has its own printInfo implementation, without the need to cast or use instanceof.
You need to cast the Card to a Guard:
((Guard) deck[i]).printGuardInfo();
The easiest, most object-oriented way to do this is to change printGuardInfo to toString:
public String toString()
{
return new StringBuilder("This card score fo the guard is: ")
.append(cardScore).append('\n')
.append("The card name is: ")
.append(cardName).append('\n')
.append("The card ability is ")
.append(cardAbility)
.toString();
}
You can then call String guardInfo = deck[i].toString(); to get the guard info and write it to standard output, a logger, etc.
public String toString() is inherited from Object, so no casting is needed to call it.
R2-D2 is right, but if you want to be more 'polymorphic' you should do something like This
public interface ICard {
public void printInfo();
}
public class Card implements ICard{
public void printInfo(
System.out.println("Card Info");
}
}
public class Guard extends Card {
public void printInfo{
System.out.println("GUARD Info");
}
}
public vlass Deck{
...
public void addGuards()
{
for(int i=0; i<5; i++)
{
deck[i] = new Guard();
deck[i].printInfo();
}
}
}
Or even use an abstract class

Grab public member of abstract class in Java

I know that when I generate an abstract class and give it public members I can grab them from the child class. But I want to do exactly that, but on a general basis. For example:
public abstract class Tile {
public int member = 0;
}
Now I create a lot of subclasses (at least 20). I have a list of mixed subclasses and I want to grab that public member.
ArrayList<Tile> tiles = new ArrayList<>();
...
for (int i = 0; i < tiles.size(); i++) {
tiles.get(i).member++; // get and do something useful with member
}
Of course the list does (as far as I know) hold subclasses of Tile. I want to be able to grab the public member from the list of subclasses without having to know which subclass it is. Is there a way to accomplish this?
For clarity, this will not compile and the editor doesn't recognize the global member on the line tiles.get(i).member.

Unknown parent variable issue in java

Recently I asked a question about why all my variables in spawned items were being set to the same damage value (Java switch statements outputting the same numbers) and that code wasn't to blame, however after some deep debugging i've found that when an item is spawned it randomises the damage and then for some reason sets that damage to every previously created item of the same type.
I have 'dagger' and 'sword' classes which extend my 'item' class. This is how I set the damage:
case 3: {Sword sword = new Sword(); World[X][Y].treasureName = "sword"; sword.setDamage(4); returnItem = sword; break;}
And this is my item class:
public abstract class Item {
//How much damage is added to the players attack.
static int damage = 0;
static int defence = 0;
public int getDefence() {
return defence;
}
public void setDefence(int defenceValue) {
defence = defenceValue;
}
public int getDamage() {
return damage;
}
public void setDamage(int damageValue) {
damage = damageValue;
}
}
And my sword class:
public class Sword extends Item {
//How much damage is added to the players attack.
static int damage = 0;
static int defence = 0;
public int getDefence() {
return defence;
}
public void setDefence(int defenceValue) {
defence = defenceValue;
}
public int getDamage() {
return damage;
}
public void setDamage(int damageValue) {
damage = damageValue;
}
}
I'm not sure what this problem is called and not sure what to google being fairly new still. I tried to override the item class but that didn't change anything and i've read about inheritance and I don't understand which part is setting every other weapon instance to the same damage. I wanted to remove the methods in the 'Item' class to see if that would fix it, however other code causing errors prevented me to do this when checking and adding together the damage of all the children of 'Item' - this required a cast of (Item) and i'm not sure of what else I can use as a cast.
Here are the referrals to the 'Item' method:
if (((Item) World[k][i].treasure).getDamage() > 9)
{
Without the cast the error is: getDamage() is undefined for the type Object.
and:
//Recalculates the players damage for recently equipped items.
for (int i = 0; i < numItems; i++) {
itemdamage += items[i].getDamage();
System.out.println("You have a " + itemNames[i] + " giving you " + items[i].getDamage() + " extra damage.");
}
What's wrong? I want to understand this so links to helpful information on why, and what i'm doing wrong would be good. Thanks.
static int damage = 0;
Having a static member means that all objects of the class same the same value. If you remove the static keyword, each object will be able to have a different value for damage.
As to the required cast, it seems that World is an array of Object type. Therefore World[k][i] is of Object type, and you can only call methods of the base Object class on it. If you want to call a method defined in the Item class, you must cast the Object to an Item (assuming the runtime type of that Object is an Item).
Your damage and defense variables should not be static. A static variable is tied to the whole class, not to any one instance of the class. As such, when you call setDamage(), even though the method is an instance method, it updates a static variable which is shared by every existing instance.
Remove the static (did you mean to use protected?) and you won't see the "for some reason sets that damage to every previously created item of the same type" behavior anymore.
See What does the 'static' keyword do in a class? for more. Here's the official Java Language Specification on static fields, as well.
You set the variables damage and defence (spelling mistake here - by the way) to be static. Which means that there's only one copy of each variables for the entire class.
Remove the static keyword before the declaration of both variables - and it'll make any new sword instance (object) - carry its own damage and defence.
Heyhey Fluidic,
I'm still fairly new to Java myself, but I think your problem is that your damage variables are set to static (and I would assume the problem would persist across your defence stats as well!)
I had this problem while learning to develop in C++. I would change a value of one of my constructors which referenced a static variable, and all of the instances would change. It's a constant belonging to the class itself, not the object.
So what's happening, is when you change the damage value; all references that use that static damage variable are being changed.
This site gives a bit of an insight on static variables!
http://www.javatpoint.com/static-keyword-in-java
Lemme know if that helps!
Andy
According to the error :
getDamage() is undefined for the type Object
I think you World array, is an array of Object instead of Item
Could you show us how you manage the World array ?

Calling a method from arraylist

For a turn-based game I want to make a build queue for a planet. User puts items to build in a queue and then, when turn is generated, everything in a queue is being built.
Right now I have a Planet class which has an ArrayList. An object of type Planet is created for each planet the player owns. The array list contains everything user has ordered this planet to build. It also contains 3 variables that store the resources currently present on the planet and 3 variables that store total number of buildings that are currently on the planet.
Every building type is also a class (because building types costs differ), I plan to put objects of corresponding type into the planets queue. I suppose that each building class should have its own building method .build();
I want to cycle through each item in the queue of the planet and launch something like .buld() method.
Building an object means subtracting some resources from the planets resource variables and adding number of buildings built to total number of buildings on a planet.
The trouble is that I don't understand the main idea, how to achieve this.
The Planet class:
public class Planet extends WorldObject implements Serializable {
private int defenses;
private int mines;
private int factories;
//it also has 3 variables from WorldObject class:
int iron;
int bor;
int ger;
ArrayList<Installation> queue;
private void build(){
for ( int i = 0; i < queue.size()-1; i++ )
{
queue.get(i).build();
}
}
}
One of the building classes:
public class Factory extends Installation {
int costIron = 10;
int costGer = 50;
public build(int amt) {
//build itself, remove res from planet, add number built to planet factory list
}
}
If I'm doing this totally wrong, I would be thankful if you say in which "direction" should I look for information.
It sounds like Planet should have a Resources object that encapsulates the resources, and that could be passed to Installation.build(). Then Installation.build() could return a object that describes what was built.
Edit: here's an example:
public class MineFactory extends Installation {
private final Resources cost;
public MineFactory(Resources cost) {
this.cost = cost.clone();
}
#Override
public Result build(Resources availableResources) {
if (!availableResources.remove(cost)) {
return Result.empty();
}
return Result.mines(2);
}
}
You need to either pass your Planet object to build as an argument so that it has access to resources, or, alternatively, do the "building" in the Panet code itself, and just have getCost on the building, that you'd call yo find out how much resources to subtract.
Personally, I'd know kinda prefer the latter approach, but that's more of a question if taste than anything else.

Not getting the correct values for variables in extended class

Just doing a quick edit up at the top of my post.
The question is if i extend a class and both classes have the same variable why is the extended class getting the original classes value.
This has been answered but would be more than happy to read more information about this.
Polymorphism isn't a strong suit of my so i'm having to relearn this stuff after not using it for months.
So i'm trying to program a game and one of the requirements is some type of list of object that can be scanned in a loop. The trouble starts with my test of ArrayList. I have 3 classes i made to be added in to my array list. Entities, Monster extends Entities, and Character extends Entities. do note Monster and Character both extends Entities class.
I decided that i should make the ArrayList and added new objects directly in to each element(the word element is normally used with array not ArrayList correct?) and use a log function i programmed to note down values of the objects in the ArrayList.
I made a for loop and ran both Monster and Character .getHP() method that they inherited from Entities and the results was the HP from Entities not Monster or Character unless i added a new value to the classes HP using the setHP(int i) method also inherited Entities.
Since my program requires most of the classes and we only need about 99% i decided to make a test project to basically do the above in a smaller form since i don't want to be copying pasting 20 or more .java files here. Anyways here's my test classes and results.
import java.util.ArrayList;
// class to test interactions between Extended classes
public class testHP {
ArrayList<Entities> ent = new ArrayList<Entities>();
public static void main(String[] args) {
///make reference varaible so i don't have to make test() and ent static.
testHP hp = new testHP();
hp.test();
}
void test(){
/// the 3 classes to the arraylist. I could of made a reference variable but didn't.
this.ent.add(new Character());
this.ent.add(new Monster());
this.ent.add(new NPC());
///prints out whats in the array list so i know that i have the correct objects.
System.out.println(this.ent);
/// this prints out { ent(i) HP "is" i } to tell which class is being called and it's HP at this point.
for(int i=0; i<ent.size();i=i+1) {System.out.println(this.ent.get(i).getHP() +" is "+ this.ent.get(i));}
/// this adds i plus 10 then does the same as the last for loop.
for(int i=0; i<ent.size();i=i+1) {
this.ent.get(i).gainHP(i+10);
System.out.println(this.ent.get(i).getHP() +" is "+ this.ent.get(i));}
}
}
abstract public class Entities {
private int HP = 1;
int getHP(){
return HP;
}
void gainHP(int hp){
HP = this.HP + hp;
}
}
///Character is to show what happens when i change the value and make it static.
public class Character extends Entities {
private static int HP = 4;
}
///monster is to show a changed variable from the super which is entities.
public class Monster extends Entities {
private int HP = 4;
}
/// NPC is a class that just to have variables from entities class that aren't edited or made static.
public class NPC extends Entities {
}
here is my results with these files as they are above. I should have put HP next to the number to the left but you get the idea.
[Character#67f1fba0, Monster#3fbefab0, NPC#133c5982]
1 is Character#67f1fba0
1 is Monster#3fbefab0
1 is NPC#133c5982
11 is Character#67f1fba0
12 is Monster#3fbefab0
13 is NPC#133c5982
My test class for the original ArrayList looks like this.
import java.util.ArrayList;
public class AreaMap extends Map {
String CLASS = "Area Map";///log requires.
ArrayList<Entities> ent = new ArrayList<Entities>();
AreaMap(){
Log.Logging(CLASS,"Testing arrayList");
//random text added to the array.
ent.add(new Character());
ent.add(new Monster());
Log.Logging(CLASS, "ent 1 has " +ent+ " in it");
for(int i=0; i < ent.size();i = i+1){
Log.Logging(CLASS, "ArrayList " + this.ent.get(i).getHealth() +" i="+i);
}
for(int i=0; i < ent.size();i = i+1){
this.ent.get(i).setHP(10+i);
Log.Logging(CLASS, "ArrayList " + this.ent.get(i).getHealth() +" i="+i);
}
}
}
And here are my result from that.
[Area Map]##[Testing arrayList]
[Area Map]##[ent 1 has [Character#2bd1e730, Monster#61a116c9] in it]
[Area Map]##[ArrayList 0 i=0]
[Area Map]##[ArrayList 0 i=1]
[Area Map]##[ArrayList 10 i=0]
[Area Map]##[ArrayList 11 i=1]
Do note that "Log" is a class i made and the method is "static Logging(String origin, String Action){System.out.println([origin]+"##"+[Action]);"
origin is always the class not that it has to be.
Sorry if this isn't clear. If you need more information to help me i'm more than willing to answer.
Basically the problem is that you're trying to declare extra variables in subclasses as if they can "override" the variable in the superclass. Variables don't work that way - they're not polymorphic.
If you need to give each class a different starting number of hit points, I suggest you create a protected constructor in Entities (which should be renamed, btw - e.g. AbstractEntity) to take the initial value of HP (which should probably be renamed hitPoints). Then each subclass would have a public constructor to call the superconstructor with an appropriate value.
For example:
public abstract class AbstractEntity {
private int hitPoints;
protected AbstractEntity(int initialHitPoints) {
this.hitPoints = initialHitPoints;
}
public int getHitPoints(){
return hitPoints
}
void gainHitPoints(int amount) {
hitPoints += amount;
}
}
public class Monster extends AbstractEntity {
public Monster() {
// Every monster starts off with 4 hit points
super(4);
}
}
Now that's just a matter of changing the initial state. If you wish the different entities to behave differently, you should override the abstract class methods within the subclasses.
I believe your problem is scoping. The HP that Entities* is accessible from your getHP, but your HP in Character and Monster are different variables that happen to have the same name. Additionally, marking HP as private means that subclasses can't access that variable - I think you have protected.
What is probably the correct solution to get rid of HP in Monster and Character, make HP in Entities protected, and set the default HP in the default constructor for Monster and Character.
* It's good style to name your objects in the singular, so this is better named as Entity.
If I understand it correctly, the problem is as follows:
You declared the attribute HP as private in class Entities and declared a new(!) variable in the subclass (see the other answers).
You can resolve the behavior by setting HP by a constructors, e. g.,
class Entitites {
private int HP;
public Entities(int hp) {
this.HP = hp;
}
}
class Monster extends Entities {
public Monster() {
super(4);
}
}

Categories