拥有以下超类:
public class SuperClass {
protected Integer a;
protected Integer b;
public void doSomething() {
this.a = 10;
}
public void doEverything() {
SuperClass.this.doSomething();
this.b = 20;
}
public static void main(String[] args) {
SuperClass instance = new SubClass();
instance.doEverything();
System.out.println(instance.a); //should print 10
System.out.println(instance.b);
}
}
以下子类:
public class SubClass extends SuperClass {
@Override
public void doSomething() {
super.doSomething();
super.a *= 10;
}
public void doEverything() {
super.doEverything();
this.b += 5;
}
}
输出:
100
25
因此,SuperClass.this.doSomething();
正在访问SubClass
的{{1}},但我需要它来访问doSomething
的{{1}}。在这种情况下,我没有SuperClass
关键字,因为我已经超级了!
有没有办法引用¹深 doSomething
,所以它会为第一个输出super
输出值?
¹我对引用感兴趣:我们当然可以将SuperClass.this.doSomething
的{{1}}提取到辅助私有方法并直接访问它子>
如果没有办法,超类方法需要访问另一个(虽然被覆盖)方法的情况是否意味着我的OOP设计不正确?为什么?
答案 0 :(得分:3)
我假设您从C ++背景来到Java。语言在概念和语法上类似,但它们在实现中是不同的。
你可以用Java实现我的想法,但结构与C ++的结构不同。
在Java中,示例中的构造SuperClass.this
与this
完全相同,因此SuperClass.this.doSomething();
恰好就是doSomething()
。那么为什么Java根本就有构造SuperClass.this
?它的含义与继承无关。它在嵌套类的上下文中很有用。
想象一下这样的结构:
class A {
class B {
public void doSomething() {
// this here refers to an instance of the class B
System.out.println(this);
// We need to write is this way,
// because this hides the this reference to the instance of A.
// A.this is the instance of A where this is nested
System.out.println(A.this);
}
}
那么如何确保能够在类中具有子类可以覆盖的方法,并且仍然能够调用特定的实现?
嗯,从严格意义上说,你不能。你可以做的是创建一个final
方法,它不能被覆盖,并从非最终方法调用它。
class SuperClass {
public void doSomething() {
doSuperClassyThing();
}
public final void doSuperClassyThing() { // cannot be overridden
...
}
}
您可以在Template Method Pattern中看到类似的方法(目标略有不同)。
答案 1 :(得分:2)
答案是你无法引用它。执行此操作的唯一方法是您已经了解的私有帮助方法。
如果你想知道原因,我想这只是因为它会无缘无故地使语言复杂化;通过使用私有帮助器方法,您始终可以获得相同的结果。语法SuperClass.this.doSomething()
已被用于其他内容。这意味着如果doSomething
是一个封闭类,则在封闭实例上调用方法SuperClass
。
答案 2 :(得分:2)
你无法做你想做的事。多态性的工作方式是做你所看到的。
这意味着没有直接的方法从SuperClass.doSomething()调用SuperClass.doSomething()而不通过SubClass.doSomething(),除非您正在使用SuperClass的实际实例。
在其他一些语言中,您有权告诉如何处理此问题,例如在c ++中使用关键字virtual,但在java中,您没有这个选项。所有方法都被动态绑定,因此您无法做到这一点。你根本不能覆盖或阻止它被覆盖。
答案 3 :(得分:1)
如果您发现自己处于这种情况,也许您应该重新考虑并认为类结构 尚未正确。
尝试实施以下方法之一:
super
的类)。由于(1.)不会像其他人一样干,(4。)留下一种解决方法的感觉,并且(2.)需要创建一个新文件并在{{1}之外引用};我认为最接近的方法是(3.),这是在SuperClass
内以某种方式引用super
的唯一解决方案(虽然它实际上是在SuperClass
内部类上引用的):< / p>
<强> SuperClass.java:强>
SuperClass
<强> SubClass.java:强>
public abstract class SuperClass {
protected Integer a;
protected Integer b;
public void doSomething() {
this.a = 10;
}
public abstract void doEverything();
public static class Impl extends SuperClass {
@Override
public void doEverything() {
super.doSomething();
this.b = 20;
}
}
public static void main(String[] args) {
SuperClass instance = new SubClass();
instance.doEverything();
System.out.println(instance.a); //prints 10
System.out.println(instance.b);
}
}