超类方法需要引用它的另一个(尽管被覆盖)方法
Superclass method needing to refer to its another (although overridden) method
具有以下超类:
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
的 doSomething
,但我需要它来访问 SuperClass
的 doSomething
。在那种情况下,我没有 super
关键字,因为我已经在 super!
有没有办法引用¹ deep SuperClass.this.doSomething
,所以它会为第一个输出值输出 10
?
¹ 我对 referencing 感兴趣:我们当然可以将 SuperClass
的 doSomething
提取到辅助私有方法,直接访问。
如果没有办法,一个超类方法需要访问它的另一个(尽管被覆盖)方法的情况是否意味着我的 OOP 设计不正确?为什么?
答案是不能参考。执行此操作的唯一方法是您已经知道的私有辅助方法方法。
如果你想知道为什么,我想这只是因为它会无缘无故地使语言复杂化;您始终可以通过使用私有辅助方法获得相同的结果。语法 SuperClass.this.doSomething()
已被用于其他用途。这意味着如果 SuperClass
是封闭实例 class,则调用封闭实例上的方法 doSomething
。
你不能为所欲为。多态性的工作方式是做你所看到的。
这意味着没有通过 SubClass.doSomething() 从 SuperClass.doSomething() 调用 SuperClass.doSomething() 的直接方法,除非您正在使用 SuperClass 的实际实例.
在其他一些语言中,您有权告诉如何处理此问题,例如在 C++ 中使用关键字 virtual,但在 java 中您没有该选项。所有的方法都是动态绑定的,所以你不能那样做。您只能不覆盖或完全阻止它被覆盖。
我假设您是从 C++ 背景来到 Java 的。这些语言在概念和语法上相似,但在实现上却不同。
你也可以在 Java 中实现我认为是你的意图,但结构看起来与 C++ 不同。
在 Java 中,您示例中的构造 SuperClass.this
与 this
完全相同,因此 SuperClass.this.doSomething();
正是 doSomething()
的样子。那么为什么 Java 有结构 SuperClass.this
呢?它的含义与继承无关。它在嵌套 classes.
的上下文中很有用
想象一下这样的结构:
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);
}
}
那么你如何确保能够在 class 中有一个子classes 可以覆盖的方法,并且仍然能够调用特定的实现?
嗯,从严格意义上说,你不能。您可以做的是创建一个无法覆盖的 final
方法,并从非最终方法调用它。
class SuperClass {
public void doSomething() {
doSuperClassyThing();
}
public final void doSuperClassyThing() { // cannot be overridden
...
}
}
您可以在 Template Method Pattern.
中看到类似的方法(目标略有不同)
如果您遇到这种情况,也许您应该重新考虑并考虑 class 结构还 不正确。
尝试实施以下方法之一:
- 组合优于继承。
- 正在创建一个新的继承级别(中间的 class 引用了
super
)。
- 与 (2.) 相同,但使用内部 class.
- 将需要的方法提取到一个单独的私有方法中,并在适用的地方调用它。
因为 (1.) 不会像其他的那样枯燥,(4.) 留下一种解决方法的感觉,并且 (2.) 需要创建一个新文件并在外部引用 SuperClass
;我认为最接近的方法是 (3.),这是唯一以某种方式在 SuperClass
中引用 super
的解决方案(尽管它实际上是在 SuperClass
内部 class):
SuperClass.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);
}
}
SubClass.java:
public class SubClass extends SuperClass.Impl {
@Override
public void doSomething() {
super.doSomething();
super.a *= 10;
}
@Override
public void doEverything() {
super.doEverything();
this.b += 5;
}
}
具有以下超类:
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
的 doSomething
,但我需要它来访问 SuperClass
的 doSomething
。在那种情况下,我没有 super
关键字,因为我已经在 super!
有没有办法引用¹ deep
SuperClass.this.doSomething
,所以它会为第一个输出值输出10
?¹ 我对 referencing 感兴趣:我们当然可以将
SuperClass
的doSomething
提取到辅助私有方法,直接访问。如果没有办法,一个超类方法需要访问它的另一个(尽管被覆盖)方法的情况是否意味着我的 OOP 设计不正确?为什么?
答案是不能参考。执行此操作的唯一方法是您已经知道的私有辅助方法方法。
如果你想知道为什么,我想这只是因为它会无缘无故地使语言复杂化;您始终可以通过使用私有辅助方法获得相同的结果。语法 SuperClass.this.doSomething()
已被用于其他用途。这意味着如果 SuperClass
是封闭实例 class,则调用封闭实例上的方法 doSomething
。
你不能为所欲为。多态性的工作方式是做你所看到的。
这意味着没有通过 SubClass.doSomething() 从 SuperClass.doSomething() 调用 SuperClass.doSomething() 的直接方法,除非您正在使用 SuperClass 的实际实例.
在其他一些语言中,您有权告诉如何处理此问题,例如在 C++ 中使用关键字 virtual,但在 java 中您没有该选项。所有的方法都是动态绑定的,所以你不能那样做。您只能不覆盖或完全阻止它被覆盖。
我假设您是从 C++ 背景来到 Java 的。这些语言在概念和语法上相似,但在实现上却不同。
你也可以在 Java 中实现我认为是你的意图,但结构看起来与 C++ 不同。
在 Java 中,您示例中的构造 SuperClass.this
与 this
完全相同,因此 SuperClass.this.doSomething();
正是 doSomething()
的样子。那么为什么 Java 有结构 SuperClass.this
呢?它的含义与继承无关。它在嵌套 classes.
想象一下这样的结构:
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);
}
}
那么你如何确保能够在 class 中有一个子classes 可以覆盖的方法,并且仍然能够调用特定的实现?
嗯,从严格意义上说,你不能。您可以做的是创建一个无法覆盖的 final
方法,并从非最终方法调用它。
class SuperClass {
public void doSomething() {
doSuperClassyThing();
}
public final void doSuperClassyThing() { // cannot be overridden
...
}
}
您可以在 Template Method Pattern.
中看到类似的方法(目标略有不同)如果您遇到这种情况,也许您应该重新考虑并考虑 class 结构还 不正确。
尝试实施以下方法之一:
- 组合优于继承。
- 正在创建一个新的继承级别(中间的 class 引用了
super
)。 - 与 (2.) 相同,但使用内部 class.
- 将需要的方法提取到一个单独的私有方法中,并在适用的地方调用它。
因为 (1.) 不会像其他的那样枯燥,(4.) 留下一种解决方法的感觉,并且 (2.) 需要创建一个新文件并在外部引用 SuperClass
;我认为最接近的方法是 (3.),这是唯一以某种方式在 SuperClass
中引用 super
的解决方案(尽管它实际上是在 SuperClass
内部 class):
SuperClass.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);
}
}
SubClass.java:
public class SubClass extends SuperClass.Impl {
@Override
public void doSomething() {
super.doSomething();
super.a *= 10;
}
@Override
public void doEverything() {
super.doEverything();
this.b += 5;
}
}