【问题标题】:Java can subclass inherit and override nested class?Java子类可以继承和覆盖嵌套类吗?
【发布时间】:2015-11-04 18:32:25
【问题描述】:

这是用于 Java Swing JToolBar:

我有自己的工具栏类,它扩展了 JToolBar,它上面有带有 ActionListener 的按钮。代码:

class ToolBar extends JToolBar {
    JButton save, reset;

    ToolBar() {
        setFloatable(false);
        setRollover(true);
        makeButtons();
    }

    makeButtons() {
        save = new JButton();
        // Icon and tooltip code
        save.addActionListener(new ButtonListener());
        add(save);

        reset = new JButton();
        // Icon and tooltip code
        reset.addActionListener(new ButtonListener());
        add(reset);

    protected class ButtonListener implements ActionListener {
        public void actionPerformed(ActionEvent event) {
        }
    }

然后我制作了这个的其他几个子类,因为我需要多个框架的多个工具栏,每个工具栏都有不同的“保存”或“重置”源/目标。为简单起见,我只给出一个:

class FullToolBar extends ToolBar {

    protected class ButtonListener implements ActionListener {
        public void actionPerformed(ActionEvent event) {
            if (event.getSource() == save) FullInput.save();
            else if (event.getSource() == reset) FullInput.reset();
        }
    }
}

FullInput 是我的其中一个 JFrame 的名称,工具栏将继续显示。它有一个静态的保存和重置方法,但是由于某种原因,当我将 FullToolBar 添加到我的 FullInput 时,按钮不起作用。

我是否误解了嵌套类可以被继承和覆盖?有什么想法/cmets甚至建议以完全不同的方式来做我在这里想要完成的事情吗?基本上,需要一种方法来使用相同工具栏的不同框架/类上的保存和重置按钮。

【问题讨论】:

    标签: java swing inheritance subclass nested-class


    【解决方案1】:

    不,您不能像这样覆盖嵌套类。有几种方法可以解决这个问题。一种是将可覆盖的方法放在主 Toolbar 类上,例如:

    class ToolBar extends JToolBar {
    
      makeButtons() {
        save = new JButton();
        // Icon and tooltip code
        save.addActionListener(new ActionListener() {
          public void actionPerformed(ActionEvent event) {
            saveButtonPressed(event);
          }
        });
      }
    
      protected void saveButtonPressed(ActionEvent event) {}
    }
    

    然后,子类可以通过覆盖saveButtonPressed 方法来自定义按下保存按钮时的操作。

    【讨论】:

    • 我最终使用了你的一半答案 =P,我保留了我的嵌套类,但在父类中(如你所说)对空方法进行了方法调用,这些方法在子类中被覆盖。跨度>
    【解决方案2】:

    我是否误解了嵌套类可以被继承和覆盖?

    是的。尽管您的 ButtonListener 类具有相同的名称,但它们彼此之间没有其他联系。嗯...嵌套类被继承,但它们不能被覆盖。例如,您可以继承一个继承类:

    class FullToolBar extends ToolBar {
        protected class ButtonListener extends ToolBar.ButtonListener {
                                               ^^^^^^^^^^^^^^^^^^^^^^
    

    但这在这里没有用,因为它仍然不会覆盖在ToolBar 中对new ButtonListener() 的调用。

    还有许多其他方法可以使这项工作。如果你真的想覆盖ButtonListener 类,你可以用调用protected ActionListener createListener() 方法替换new ButtonListener() 的使用,以便在子类中被覆盖,这样它们就可以提供他们想要的任何监听器类实现。在这种情况下,这可能会过于复杂。

    这里更简单的解决方案是让ToolBar直接实现ActionListener,并覆盖子类中的actionPerformed方法:

    class ToolBar extends JToolBar implements ActionListener {
        ...
    
        void makeButtons() {
            ...
            save.addActionListener(this);
            ...
        }
    
        public void actionPerformed(ActionEvent event) {
        }
    }
    
    class FullToolBar extends ToolBar {
        @Override
        public void actionPerformed(ActionEvent event) {
            if (event.getSource() == save) FullInput.save();
            else if (event.getSource() == reset) FullInput.reset();
            else super.actionPerformed(event);
        }
    }
    

    作为一种变体,如果您想阻止 actionPerformed 在 ToolBar 中公开,请改为使用受保护的方法,命名为您想要的任何名称,并在子类中覆盖它。使用 Java 8 的方法引用语法将处理程序方法与按钮连接起来:

    class ToolBar extends JToolBar {
        ...
    
        void makeButtons() {
            ...
            save.addActionListener(this::onButtonClick);
            ...
        }
    
        protected void onButtonClick(ActionEvent event) {
        }
    }
    
    class FullToolBar extends ToolBar {
        @Override
        protected void onButtonClick(ActionEvent event) {
            if (event.getSource() == save) FullInput.save();
            else if (event.getSource() == reset) FullInput.reset();
            else super.onButtonClick(event);
        }
    }
    

    还有一个想法:你真的需要ToolBar 为这些按钮设置事件侦听器吗?你可以在子类中这样做:

    class ToolBar extends JToolBar {
        ...
    
        protected void makeButtons() {
            save = new JButton();
            add(save);
            reset = new JButton();
            add(reset);
        }
    }
    
    class FullToolBar extends ToolBar {
        @Override
        protected void makeButtons() {
            super.makeButtons();
            save.addActionListener((ActionEvent e) -> FullInput.save());
            reset.addActionListener((ActionEvent e) -> FullInput.reset());
        }
    }
    

    【讨论】:

    • 哦,抱歉,我没有静态,那只是我测试,看看将所有内容更改为静态是否可以做任何事情;编辑了它。
    • @Override 是什么意思?
    • @EdwardGuo @Override 是可选的,不会更改调用的方法实现,但它记录了方法被覆盖的事实,并让编译器警告被覆盖方法的意外拼写错误姓名/签名。
    • 好的,谢谢。最后一个小约定问题。在“implements ActionListener”和import java.awt.event.ActionListener;之间有没有更常用的方式来使用ActionListener?还是主要只是依赖于用例。
    • @EdwardGuo 我不是 100% 确定您的意思,但至少有 4 种方法可以创建 ActionListener 实例。 (1)创建一个implements ActionListener的命名类,如您的问题所示。 (2)创建一个匿名类new ActionListener() { ... },如@jtahlborn 的答案所示。 (3)使用我的答案(save.addActionListener(this::onButtonClick);)中所示的方法参考。 (4) 使用 lambda 语法:save.addActionListener((ActionEvent e) -> FullInput.save());.
    猜你喜欢
    • 1970-01-01
    • 2022-06-18
    • 2013-09-18
    • 2021-03-22
    • 2017-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-29
    相关资源
    最近更新 更多