user3122986 user3122986 - 1 month ago 5x
Java Question

Method in child class not called (properly)

I have a class "FileButton". It's purpose is to link a file to a JButton, FileButton inherits from JButton. Child classes inherit from this to do usefull stuff with the file linked to the button.

The Class JingleCardButton is one of those child classes. This Child Class has a method that can play the jingle linked to the JingleCardButton when the button is clicked with the method "playSound()". This method isn't available in other child classes that inherit from FileButton

Also, i have a class Card that maintains a grid of FileButton objects on a specified JPanel. The Class JingleCard inherits from Card and maintains JingleCardButton objects.

Since every kind of Card needs to store all of its, the 2D buttonGrid array is declared in the base class Card.

protected FileButton[][] buttonGrid; //the 2d area containing all FileButton objects is declared in "Card".

This is the constructor in JingleCard

public JingleCard(JPanel p, int xdim, int ydim, JToggleButton editButton) {
super(p,xdim,ydim,editButton); // calling the constructor in Card
buttonGrid= new JingleCardButton[xdim][ydim];
for (int row= 0; row< xdim; row++) {
for (int column= 0; column< ydim; column++) {
buttonGrid[row][column] = new JingleCardButton(null);


Now i have a JingleCard, a 2D array filled with JingleCardButtons. After adding the mp3 file to the button (there's no file linked automatically when creating a card) with the GUI.

Now i should be able (i think so) to play the jingle assigned with the gui to a JingleCardButton somewhere in the JingleCard's ButtonGrid.

buttonGrid[row][column].playSound(); //syntax to play the sound is just like here: instance_of_JingleCardButton.playSound();

I have no idea why, but when compiling this in Netbeans, this produces an error... According to Netbeans, the method PlaySound() can't be found in the class FileButton. (that's true, because it's in the child class JingleCardButton).

What's causing this problem? I'm sure that buttonGrid contains JingleCardButton objects, and calling playSound() should work. I don't see what's going wrong.

(some of the classes mentioned also implements ActionListener en Serializable)


Your buttonGrid is an array of FileButton, and so the compiler sees each item in the array as being of FileButton type. Now even if you fill the array with JingleCardButton objects, the Java compiler will only allow you to call FileButton methods on the items in the array. You can sort of understand the rationale by thinking that since Java has no way of knowing that later you might not switch out an item in the array with a FileButton object of different sub-type, it has to err on the side of safety and limit what you can do with that variable.

One possible solution is to check the type object held by the variable using the instanceof operator, and then casting the variable to that of JingleCardButton

if (buttonGrid[row][column] instanceof JingleCardButton) {
    ((JingleCardButton) buttonGrid[row][column]).playSound();

... but that results in dirty code, code that is brittle and easily broken.

Better is to not even sub-type JButton since you don't appear to be wanting to change the innate properties of a JButton, but rather its behaviors when pressed. This behavior is not dictated by the button itself but rather by what Action it is set to, or what ActionListeners have been added to it. For this reason I strongly encourage you to create classes that extend AbstractAction and not JButton, not unless there are other JButton behaviors, behaviors that are unrelated to its action listener behavior, that you wish to modify.