Java 未调用子类中的方法(正确)

Java 未调用子类中的方法(正确),java,inheritance,Java,Inheritance,我有一个类“FileButton”。它的目的是将文件链接到JButton,FileButton继承自JButton。子类继承自此,以便对链接到按钮的文件执行有用的操作 类JingleCardButton就是这些子类之一。此子类有一个方法,当使用方法“playSound()”单击按钮时,该方法可以播放链接到JingleCardButton的铃声。此方法在继承自FileButton的其他子类中不可用 此外,我还有一个类Card,它在指定的JPanel上维护一个由FileButton对象组成的网格。类

我有一个类“FileButton”。它的目的是将文件链接到JButton,FileButton继承自JButton。子类继承自此,以便对链接到按钮的文件执行有用的操作

JingleCardButton就是这些子类之一。此子类有一个方法,当使用方法“playSound()”单击按钮时,该方法可以播放链接到JingleCardButton的铃声。此方法在继承自FileButton的其他子类中不可用

此外,我还有一个类Card,它在指定的JPanel上维护一个由FileButton对象组成的网格。类JingleCard继承自卡片并维护JingleCardButton对象

由于每种都需要存储其所有属性,因此2D buttonGrid数组在基类中声明

   protected FileButton[][] buttonGrid; //the 2d area containing all FileButton objects is declared in "Card". 
这是KingleCard中的构造函数

  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);
            buttonGrid[row][column].addActionListener(this);
            p.add(buttonGrid[row][column]);
        }

        p.doLayout();
    }        
            p.doLayout();
        }
    }
我不知道为什么,但在Netbeans中编译时,会产生一个错误。。。根据Netbeans,在类FileButton中找不到方法PlaySound()。(这是真的,因为它在child类中JingleCardButton

是什么导致了这个问题?我确信buttonGrid包含JingleCardButton对象,调用playSound()应该可以。我不知道出了什么问题


(提到的一些类还实现了ActionListener en Serializable)

您的buttonGrid是一个FileButton数组,因此编译器将数组中的每个项都视为FileButton类型。现在,即使使用JingleCardButton对象填充数组,Java编译器也只允许对数组中的项调用FileButton方法。您可以通过这样的想法来理解其基本原理:因为Java无法知道以后您可能不会在数组中切换具有不同子类型的FileButton对象的项,所以它必须在安全方面出错,并限制您可以对该变量执行的操作

一种可能的解决方案是使用instanceof操作符检查变量持有的类型对象,然后将变量强制转换为JingleCardButton的类型对象

if (buttonGrid[row][column] instanceof JingleCardButton) {
    ((JingleCardButton) buttonGrid[row][column]).playSound();
}
。。。但这会导致脏代码,即脆弱且容易损坏的代码


更好的做法是甚至不要子类型JButton,因为您似乎不想更改JButton的固有属性,而是希望更改其在按下时的行为。此行为不是由按钮本身决定的,而是由它设置为什么操作或添加了什么ActionListeners来决定的。出于这个原因,我强烈建议您创建扩展AbstractAction而不是JButton的类,除非您希望修改其他JButton行为,这些行为与其动作侦听器行为无关。

首先,您的类不应该扩展JButton,而是希望从AbstractAction进行扩展,然后用你的子类设置每个按钮的动作。按钮的“动作”,当按下时它所做的,不是JButton本身的一部分,而是它的ActionListener或者更好的,它的动作的一部分,这就是为什么我强烈要求你做这个根本性的改变。你在代码中说你正在调用FileButton对象。。。“protected FileButton[][]buttonGrid”在调用方法PlaySound()时,您需要更改它或仅强制转换它。简单地试一下:((JingleCardButton)buttonGrid[row][collumn]).playSound()@HovercraftFullOfEels:谢谢你给我的好提示。我以后会记住这一点。今天我学到了一些新东西。@nosbor谢谢你的简单解决方案。我想我混淆了一些继承的原则。
if (buttonGrid[row][column] instanceof JingleCardButton) {
    ((JingleCardButton) buttonGrid[row][column]).playSound();
}