在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()
,则会调用bar()
中定义的A
方法,该方法会调用foo()
在B
中覆盖以打印&#34 ;来自B&#34;的Foo。
有没有办法可以强制bar()
方法调用foo()
而不是A
中定义的B
方法?就像我可以使用super.foo()
中的B
来调用foo()
中定义的A
方法一样?不幸的是,使用this.foo()
仍然会调用子类的版本。即使((A) this).foo()
或A.this.foo()
之类的内容也无效。
显然,我可以在foo()
中定义A
的私有版本或最终版本,然后调用它。但我希望找到一个解决方案,我所做的就是改变重要的线路#34;在上面的代码示例中,以一种不同的方式调用foo()使其打印出来&#34; Foo来自A&#34;,最好没有像反射这样的技巧。
答案 0 :(得分:1)
您的对象 是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
s 是绿色,总是(除非它们腐烂,但那是另外一罐香蕉)!一旦你有一个GrannySmithApple
,它就会不再一个Apple
,除非你能用普通的{{1}完成所有相同的事情。 }(Apple
,printColor
等。)有意义吗?从常规eat
到Apple
的转换之间没有任何变化的事情显然仍然相同。
答案 1 :(得分:1)
您可以在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”。
答案 2 :(得分:0)
foo()
总是调用new ...
语句中使用的类的实例方法。
简而言之,我认为你的问题的答案是 NO ,它无法完成。它会阻止您完全覆盖部分行为。
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() {
...
}
}
答案 3 :(得分:0)
据我所知,B
对象将始终调用自己的foo()
方法。话虽如此,可以定义B.foo()
来调用超类'foo()
方法。例如,您可以按如下方式定义B
:
class B extends A {
@Override public void foo() {
super.foo();
}
}
这样做会B
来自foo
A
。但这样做会让它始终如此。
答案 4 :(得分:0)
有这样的经验法则
In Inheritance the most specific version of the method for that class is called.
- 因此,如果在{strong> B实例上调用它,将始终调用foo()
Class B
方法。
- 如果您希望使用上述代码调用foo()
Class A
方法,则需要使用super
关键字。
例如:
class B extends A {
@Override
void foo() {
super.foo();
}
}
答案 5 :(得分:0)
this
引用“此对象”,而不是“此类”。
这意味着如果您有一个扩展B
的对象A
,当它在超类A
中执行提及this
的方法时,它实际上会指向B
的实例,因此将在B
上执行该方法。
您可以将A
中的方法视为默认方法。如果在您的实际对象B
中覆盖该方法,则会改为始终。
我建议您更改您的设计并使用组合而不是继承:这样可以确保明确分离关注点,并使您的代码更容易理解和测试
答案 6 :(得分:0)
正如其他人所说,没有直接的方法可以做到这一点,但你可能会考虑这种结构的变体:
void bar() {
ClassA self = new ClassA();
self.foo(); // <-- This is the important line!
}
答案 7 :(得分:0)
要么使你的方法静态(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
}