Reputation: 13
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.
Upvotes: 1
Views: 114
Reputation: 7347
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
).
Upvotes: 5
Reputation: 1891
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
Upvotes: 2
Reputation: 48404
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
.
Upvotes: 3
Reputation: 8202
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.
Upvotes: 2
Reputation: 1624
You need to cast the Card
to a Guard
:
((Guard) deck[i]).printGuardInfo();
Upvotes: 2