父类非抽象方法无法访问子类同名属性的问题求助
问题分析与解决:Java继承中父类方法无法访问子类属性的问题
你碰到的这个问题其实是Java继承里典型的变量隐藏问题,核心原因很简单:父类的私有属性和子类的同名属性完全是两个毫不相干的变量,父类的checkFade方法根本看不到子类里的那两个属性,自然只会操作自己的私有变量。
为什么会这样?
- 父类中用
private修饰的fadeTriggered和flagFade是严格封装在父类内部的,子类无法继承,也不能直接访问。 - 你在
BackgroundSnow里重新定义了protected boolean fadeTriggered和protected int flagFade,这相当于在子类里新建了两个完全独立的成员变量,和父类的同名变量没有任何关联。当你调用父类的checkFade方法时,方法里操作的始终是父类自己的那两个私有属性,和子类的属性完全不搭边。
解决办法(两种推荐方案)
方案一:调整父类属性权限,子类不再重复定义同名属性
这是最符合继承设计思路的方案:把父类的私有属性改成protected(或者保持private但提供getter/setter),让子类可以继承这些属性,不需要自己重新定义。
修改后的父类代码:
public abstract class Background { // 将私有属性改为protected,允许子类继承访问 protected boolean fadeTriggered; protected int flagFade; // 保留必要的getter/setter方法,方便外部或子类操作 public boolean getFadeTriggered() { return fadeTriggered; } public void setFadeTriggered(boolean fadeTriggered) { this.fadeTriggered = fadeTriggered; } public int getFlagFade() { return flagFade; } public void setFlagFade(int flagFade) { this.flagFade = flagFade; } // 新增抽象方法getID,强制子类实现 public abstract int getID(); public void checkFade(Background fadeFrom, Background fadeInto, SpriteBatch batch, ParallaxBackground parallaxBackground) { //Clean up if (fadeFrom.getFadeTriggered()) { fadeFrom.setFadeTriggered(false); if (fadeFrom.getFlagFade() > 0) { fadeFrom.setFlagFade(0); } } //Fade if (!fadeTriggered) { fadeTriggered = true; flagFade = 1000; } if (flagFade > 0) { parallaxBackground.draw(batch, this.getID(), 1); parallaxBackground.draw(batch, fadeInto.getID(), flagFade * .001f); flagFade--; } else { parallaxBackground.draw(batch, this.getID(), 1f); } } }
修改后的子类代码(删除重复属性,实现抽象方法):
public class BackgroundSnow extends Background { private ArrayList<ParallaxTexture> textures; private int textureCount; private final String biomeName = "Default"; private final int id = 1; // 删掉重复定义的fadeTriggered和flagFade,直接继承父类的属性 public BackgroundSnow() { int i = 1; while (true) { if (!Gdx.files.internal("backgrounds/parallax/" + biomeName + "/img" + i + ".png").exists()) { this.textureCount = i - 1; break; } i++; } Printer.debugPrintToConsole(ParallaxBackground.class, "Parallax Backgrounds found: " + Integer.toString(textureCount)); textures = new ArrayList<>(); for (int j = 1; j < textureCount + 1; j++) { textures.add(new ParallaxTexture(j, biomeName)); } } // 实现父类的抽象getID方法 @Override public int getID() { return id; } }
方案二:父类属性保持私有,方法内用getter/setter操作属性
如果不想修改父类属性的访问权限,那可以把checkFade方法里直接操作属性的地方全部换成getter/setter调用,这样方法里操作的就是当前实例(子类继承的父类属性):
比如父类的checkFade方法里的这段代码:
//Fade if (!fadeTriggered) { fadeTriggered = true; flagFade = 1000; }
改成:
//Fade if (!getFadeTriggered()) { setFadeTriggered(true); setFlagFade(1000); }
同理,其他直接访问flagFade的地方也换成getFlagFade()和setFlagFade(),这样就能保证操作的是当前实例的属性,而不是父类自己的私有变量。
额外注意事项
- 绝对不要在子类中重新定义和父类同名的属性,这种变量隐藏的做法会让代码逻辑变得混乱,是非常糟糕的编码习惯。
- 继承的核心是复用父类的特性,子类只需要专注于实现自己特有的属性和方法,或者重写父类的方法来改变行为。
内容的提问来源于stack exchange,提问作者CrystalRain
相关产品推荐
相关产品推荐

