1

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.

3
  • 1
    Have you tried casting it properly (deck[i]).printGuardInfo();, Doh! just realised that is not quite right try ((Guard)deck[i]).printGuardInfo(); Commented Nov 2, 2016 at 11:35
  • do you know about instanceof and casting? Commented Nov 2, 2016 at 11:35
  • Your code will be clearer if you use Card instead of Cards. Commented Nov 2, 2016 at 11:44

5 Answers 5

5

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).

Sign up to request clarification or add additional context in comments.

3 Comments

With the additional note that the type name should really be Card.
Thank you so much. This helps me understand interfaces better and solves my problem.
Also, thank you Chrylis on the advice on naming, really appreciated.
3

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.

Comments

2

You need to cast the Card to a Guard:

((Guard) deck[i]).printGuardInfo();

Comments

2

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.

Comments

2

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.