Java 为什么使用实例变量的数据阴影在我的程序中不起作用?

Java 为什么使用实例变量的数据阴影在我的程序中不起作用?,java,swing,inheritance,scope,Java,Swing,Inheritance,Scope,对于游戏GUI,我有三个类,如下所示: //this is the parent class. import javax.swing.*; import java.awt.*; public class GameGui extends JFrame{ public void decorateButton(JButton aBut,Color forg,Color back){ Font afont = new Font(Font.SANS_SERIF,Font.PL

对于游戏GUI,我有三个类,如下所示:

//this is the parent class.
import javax.swing.*;
import java.awt.*;
public class GameGui extends JFrame{
      public void decorateButton(JButton aBut,Color forg,Color back){
         Font afont = new Font(Font.SANS_SERIF,Font.PLAIN,18);
         aBut.setFont(afont);
         aBut.setBackground(back);
         aBut.setForeground(forg);
      }
      public void setFrameDefault(){
         this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
         this.setSize(400, 475);
         this.setLocationRelativeTo(null);
         this.setResizable(false);
     }
     public void setConstraints(int x,int y,int weightx,int weighty,GridBagConstraints gbc){
         gbc.weighty=weighty;
         gbc.weightx=weightx;
         gbc.gridx=x;
         gbc.gridy=y;
     }
}

//this class is for result to be shown for the game.

import javax.swing.*;
import java.awt.*;
class Result extends GameGui{
      JPanel mainPanel = new JPanel();
      JLabel backImage = new JLabel();//I want this variable to be shadowed by the subclass variable,but it is not happening. 
      JButton continueGame = new JButton("continueGame");
      JButton exitGame = new JButton("exitGame");
      public Result(){
            this.setFrameDefault();
            backImage.setLayout(new BorderLayout());
            this.setContentPane(backImage);
            mainPanel.setLayout(new GridBagLayout());
            decorateButton(continueGame,Color.green,Color.white);
            decorateButton(exitGame,Color.green,Color.white);
            setGui();
      }
      public void setGui(){
            GridBagConstraints gbc = new GridBagConstraints();
            mainPanel.setOpaque(false);
            gbc.gridy=200;
            gbc.gridx=0;
            gbc.insets=new Insets(410,0,0,130);
            mainPanel.add(continueGame,gbc);
            gbc.gridx=GridBagConstraints.RELATIVE;
            gbc.insets = new Insets(410,0,0,0);
            mainPanel.add(exitGame,gbc);
            setFrameDefault();
            this.getContentPane().add(mainPanel);
      }

 }

 //this class is for showing the result for a Win.

 import javax.swing.*;
 import java.awt.*;
 public class Win extends Result{
        JLabel backImage = new JLabel(new ImageIcon("C:\\Users\\BSK\\Desktop\\win.png"));//Problem is here as i have declared the same named JLabel as in Result class but iam not getting the image as background.
        public static void main(String[] args) { //this main method is for testing.
            Win w = new Win();
            w.setVisible(true);
        }
 }
在层次结构的末尾,我需要两个类,分别是
Win
feel
(第二个类我还没有实现)。我需要这个类,因为我希望wining帧和feel帧只在图像中有所不同。
所以我的问题是,尽管我在
Result
Win
两个类中都声明了与
backImage
同名的JLabel,但为什么我没有在背景中获取图像?我已经将图像放入
Result
类的
JLabel
backImage
中进行了测试,然后它就工作了!但我想利用数据阴影的优势,因为在我的
击败
类(它也扩展了结果)中,我将命名
JLabel
,与
backImage
同名,但设置了不同的图像。我希望您理解,那么出路是什么?
提前谢谢


注意请使用您的图像进行测试。

阴影会影响名称所指的变量。也就是说,由于子类
Win
定义了自己的
backImage
实例变量,因此引用
backImage
Win
方法将引用
Win
中的实例变量(及其值),而不是超类
Result
中的实例变量

阴影不会替换变量和其他对象指向的对象。也就是说,超类
Result
仍然定义自己的
backImage
实例变量,而
Result
的方法仍然引用该变量(以及它的值)。所以
Win#backImage
shadows
Result#backImage
但它不会改变结果的工作方式

还要注意,初始化行如
JLabel backImage=…
作为类构造函数的一部分运行,子类
Win
的构造函数从运行其超类
Result
构造函数开始。因此,如果子类没有声明另一个
backImage
,并且它的构造函数为继承的实例变量
Result#backImage
分配了一个新值,那么这将在
Result
构造函数构建内容窗格之后发生,因此它不会更改显示

您可以更改
背景图像
对象的内容:

public class Win extends Result {
  public Win() {
    super();
    backImage.setIcon(new ImageIcon("C:\\Users\\BSK\\Desktop\\win.png"));
  }

  ...

要修改
Win
子类的backImage图标,Java中的字段不会被重写为方法,因此这对您不起作用。幸运的是,有很多解决方案


其中之一(我肯定不是说最好的!)是使用抽象的
getIcon()
方法或其他方法将
Result
游戏抽象化,并从
setGui()
方法调用它,然后,您的赢/输课程将返回不同的图标。

请详细说明您的第一行。。如果可以……谢谢放弃。更改标签图标后,代码可能还必须请求重新显示窗口。您是说
Win
类将引用其自己的JLabel,但为什么结果不符合预期?否。Win类不应声明其自己的backImage变量,也不应创建另一个JLabel实例。只需更改已链接到组件树的现有JLabel的图标。顺便说一句,上面的帖子回答了关于阴影做什么和不做什么的问题,并提供了最小的代码更改。更好的设计可以省略子类(这不是子类的好用法),或者添加
Result
方法来更改其背景,或者添加
Result
构造函数参数来指定背景。后一种情况可能有一个始终使用默认背景的无参数构造函数。但是这不是重写,如果没有定义
JLabel
,那么
Result
类如何使用它的其他方法呢?JLabel仍然会在
Result
类中删除,方法
getIcon()
也将在其中声明,只需在
setGui()
中初始化您的背景,但使用您的
getIcon()
方法,而不是特定的图标。然后在
Win
类中重写它以返回您实际需要的图标。虽然
Win
可以重写
Result#getIcon()
方法,但是重写构造函数调用的方法通常是一个坏主意,因为它在子类构造函数运行之前被调用。这可以通过在构造函数之后进行UI构建工作来解决。aaa,没错,我想要加载警告,从构造函数调用可重写方法是个糟糕的主意(根据自己的经验),我没有注意到
setGui()
是从构造函数调用的。看起来您在这里误用了继承:您在合成效果更好的地方使用了继承。@HoverCraftFullOfels如果您能提供详细的答案……很多thanx@HovercraftFullOfEels请描述一下……等待你的回答。