![](/img/trans.png)
[英]Java: calling a super class' protected method from a subclass - not visible?
[英]Java: Calling function in “this” class rather than a subclass (analog to “super”)
在Java中是否有可能以这样的方式调用可覆盖的方法:它总是执行“本地定义的”版本而不是从子类中重写的版本? 也就是说有一个模拟super
引用这个类,而不是超类?
让我举一个代码示例,希望能说清楚我正在尝试做什么:
class A {
void foo() {
System.out.println("Foo from A");
}
void bar() {
foo(); // <-- This is the important line!
}
}
class B extends A {
@Override
void foo() {
System.out.println("Foo from B");
}
}
如果我执行new B().bar()
,它将调用A
定义的bar()
方法,该方法将调用foo()
视为在B
重写以打印“Foo from B”。
有没有办法可以强制bar()
方法调用A
定义的foo()
方法而不是B
? 就像我可以在B
使用super.foo()
来调用A
定义的foo()
方法一样? 不幸的是,使用this.foo()
仍然会调用子类的版本。 甚至像((A) this).foo()
或A.this.foo()
这样的东西也行不通。
显然,我可以简单地在A
定义foo()
的私有版本或最终版本,然后调用它。 但是我希望有一个解决方案,我所做的就是将上面代码示例中的“重要线”更改为调用foo()的不同方式,让它打印“Foo from A”,最好不要像反射这样的技巧。
你的对象是 B
它不是 A
! 这是一个例子:
public class Apple {
public void printColor() {
System.out.println("I am red");
}
public void bar() {
printColor();
}
}
然后是子类:
public class GrannySmithApple extends Apple {
public void printColor() {
System.out.println("I am green");
}
}
GrannySmithApple
是绿色的 ,总是(除非它们腐烂,但那是另外GrannySmithApple
香蕉)! 一旦你有了一个GrannySmithApple
,它就不再是Apple
了,除非你可以用普通的Apple
( printColor
, eat
等)做一切相同的事情。有意义吗? 从常规Apple
到GrannySmithApple
的转换之间没有任何变化,显然仍然是相同的。
你可以在A中调用一个“内部” foo()
。
class A {
private void fooInternal() {
System.out.println("Foo from A");
}
void foo() {
fooInternal();
}
void bar() {
fooInternal();
}
}
class B extends A {
@Override
void foo() {
System.out.println("Foo from B");
}
}
new B().bar()
现在将打印“Foo from A”,而new B().foo()
将打印“Foo from B”。
foo()
总是调用new ...
语句中使用的类的实例方法。
总之,我认为你的问题的答案是否定的 ,不能做到。 它会阻止您完全覆盖部分行为。
class A {
method1() {
...
method2();
...
}
class B extends A {
// You can override method2 here to change the behaviour of method1
// because it will call **your** version of method2
// You **don't** have to override method1 to achieve that
method2() {
...
}
}
据我所知, B
对象总是调用自己的foo()
方法。 话虽如此,可以定义B.foo()
来调用超类' foo()
方法。 例如,您可以按如下方式定义B
:
class B extends A {
@Override public void foo() {
super.foo();
}
}
而这样做将有B
调用foo
从A
。 但这样做会让它始终如此。
有这个经验法则:
In Inheritance the most specific version of the method for that class is called.
-因此,如果在B的实例上调用它,将始终调用Class B
的foo()
方法。
-仍然如果你想使用上面提到的代码调用Class A
的foo()
方法,那么你将需要super
关键字。
例如:
class B extends A {
@Override
void foo() {
super.foo();
}
}
this
引用了“这个对象”,而不是“这个类”。
这意味着,如果你有一个对象B
扩展A
,当它执行超的方法A
是提到this
,它实际上指向的实例B
,因此将执行的方法B
。
您可以将A
中的方法视为默认方法 。 如果在实际对象B
重写该方法,则将始终调用它。
我建议你改变你的设计并使用组合而不是继承 :这将确保明确分离关注点,并使你的代码更容易理解和测试。
正如其他人所说,没有直接的方法可以做到这一点,但你可能会考虑这个结构的变体:
void bar() {
ClassA self = new ClassA();
self.foo(); // <-- This is the important line!
}
要么使你的方法静态(baadddddd),要么改变你的设计。
实际上,为子类提供默认行为是没有意义的,它被定义为适应相关方法。
由于您的foo()
方法似乎有所不同,您可以实现这样的策略模式:
interface BarProcess{
void foo();
}
public class DefaultBarProcess implements BarProcess{
void foo() {
System.out.println("Foo from A");
}
}
public class AnotherBarProcess implements BarProcess{
void foo() {
System.out.println("Foo from B");
}
}
class A {
private BarProcess barProcess;
public A(Bar barProcess){
this.barProcess = barProcess;
}
void bar() {
barProcess.foo();
}
}
class B extends A { //deprecated! No need to exist
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.