1

I have a question about the use of data structures such as ArrayLists in a simple inheritance structure. I'm having a difficult time wording it: hopefully you can understand what I am trying to ask.

I have a Superclass Parrot and a Subclass PirateParrot extending Parrot. In Parrot, I have the following method:

 public String speak() {
     int rand = (int)(Math.random() * sounds.size());
     return sounds.get(rand);
    }

Which returns a random string in an ArrayList called sounds which is created in the Parrot class.

If I create a separate instance of PirateParrot called polly, which also has its own ArrayList, and try to call polly.speak(); without any implicit implementation for the speak method in the PirateParrot class, I get thrown an "Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0"

If I specifically copy/paste in the speak() method from Parrot into PirateParrot, the code compiles fine and runs properly. What exactly was the problem previously? Is there a way to make this run correctly without having to copy/paste the speak() method into PirateParrot? Thanks!

2
  • 1
    FYI, it's almost certainly better to use Random.nextInt(sounds.size()), which would also have the side effect of throwing an exception when sounds is empty -- which appears to be what's happening. Commented Apr 11, 2012 at 5:42
  • Okay, yeah I wasn't sure about the proper syntax for Math.Random- thanks. Commented Apr 11, 2012 at 5:47

3 Answers 3

3

If I understand the problem correctly, then the simplest fix would be to not declare another sounds variable in PirateParrot. Instead, make sure sounds is declared protected in Parrot, and then in the PirateParrot constructor just populate the inherited sounds variable with whatever sounds you want the PirateParrot to have.

Another alternative might be to have a getSounds() method that returns the list and call getSounds() from inside of speak() instead of referencing sounds directly. Then PirateParrot would just need to override getSounds() to return its version of sounds.

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

2 Comments

Worked perfectly. I have never utilized the protected keyword. Thank you!
protected is an important keyword to understand if you're going to be doing things with inheritance. Here's a decent overview: docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
1
public class Parrot {
  private final ArrayList<String> sounds;

  private static ArrayList<String> REGULAR_PARROT_SOUNDS = new ArrayList<String>();
  static {
    REGULAR_PARROT_SOUNDS.add(...);
    ...
  }

  protected Parrot(ArrayList<String> sounds) {
    this.sounds = sounds;
  }

  public Parrot() {
    this(REGULAR_PARROT_SOUNDS);
  }
}

public class PirateParrot {
  private static ArrayList<String> PIRATE_PARROT_SOUNDS = ...;

  public PirateParrot() {
    super(PIRATE_PARROT_SOUNDS);
  }
}

Comments

1

You are not initializing and populating the sounds before calling it, do the following:
initialize and populate sounds in the constructor of PirateParrot and then call superclass' speak method.

2 Comments

I would say sounds is initialized (otherwise a NPE would have been thrown) - but it is simply empty
by initializing i meant make it not empty ;-) (by filling it)

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.