超类中的按钮仍在子类中

时间:2013-10-26 20:02:39

标签: java swing inheritance

在我的超类构造函数中,我有一些导致其他子类的按钮。但是,这些子类也会继承这些按钮,即使它们不在它们的构造函数中。如何删除这些按钮以显示在我的子类中?我正在使用javax.swing。

好的,这是一个代码示例。我很确定我做OOP完全错了......

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;

public class Big extends JFrame implements ActionListener
{
    static private JPanel p1;
    static private JButton b1;    
    public Big(){    
        setSize(700,400);
        p1 = new JPanel();
        b1 = new JButton("Go to subclass");
        b1.addActionListener(this);
        p1.add(b1);
        add(p1, BorderLayout.NORTH);
        setVisible(true);
    }

    public void actionPerformed (ActionEvent e){
        if(e.getSource() == b1){
            setVisible(false); 
            Small subclass = new Small();
        }
    }
}

第二课:

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.util.*;


public class Small extends Big implements ActionListener
{
    static private JButton b2;
    static private JPanel p2;
    public Small(){    
        setSize(700,400);
        p2 = new JPanel();
        b2 = new JButton("Hello!");
        p2.add(b2);
        add(p2, BorderLayout.SOUTH);
        setVisible(true);
    }
    public void actionPerformed (ActionEvent e){}
}

3 个答案:

答案 0 :(得分:2)

根据您发布的代码,我认为没有理由使用继承。我建议你不要继承,问题就会消失。

此外:

  • 不要使用静态变量。

答案 1 :(得分:1)

OOP意义上的继承 与类的构造函数中的代码无关。事实上,情况正好相反;在构造函数外部声明的变量和的其他方法继承,在构造函数内声明的变量继承。

但是,是的,在其构造函数中添加到Component或JComponent的对象将由子类“继承”(但不是在继承一词的OOP意义上),除非它们在子类中被删除。因此,通过调用子类中的remove,可以快速,有点愚蠢地解决这个问题。

虽然我不会这样做。更好的方法可能是在超类中调用方法createButtons,并在子类中覆盖它以不执行任何操作,但如果以这种方式执行,请注意不要在它存在之前引用任何内容。

但是根据你现在发布的代码,我认为在这里使用继承是没有意义的。

答案 2 :(得分:1)

构造函数必须始终调用超类的构造函数作为它们的第一件事。如果你没有明确地写这个,编译器会自动插入调用(假设超类中有一个无参数构造函数要调用;否则它要求你自己这样做)。所以Small的构造函数的实际开头是这样的:

public Small() {
    super(); // call Big() constructor
    setSize(700,400);
    ...

这就是为什么它似乎继承了按钮“即使它们不在它们的构造函数中”。

您可以避免这种情况的一种方法是将创建面板和按钮的代码移动到您可以覆盖的createGUI()方法中。与构造函数不同,方法不需要调用任何超类方法,如果他们不想:

public class Big extends JFrame implements ActionListener {
    ...

    public Big() {
        createGUI();
    }

    protected void createGUI() {
        // Init buttons of Big here.
    }
}

public class Small extends Big {
    // This constructor is optional; if you remove it, the
    // compiler will insert one that looks exactly like this.
    public Small() {
        super();
    }

    @Override
    protected void createGUI() {
        // Init buttons of Small here.
        // Big's constructor calls this method, but it has been overridden,
        // so Big's implementation of this method will not execute for
        // instances of Small (unless you call super.createGUI(); on purpose).
    }
}

我并不是说这种改变是个好主意,我认为不是。正如其他人所指出的那样,当不想继承Big的代码或其行为或其字段时,为什么Small扩展Big并不清楚。我只想解释为什么超类按钮出现了。这是因为构造函数必须调用超类构造函数。