Java:在“this”类中调用函数而不是子类(类似于“super”)

时间:2012-11-15 17:31:36

标签: java inheritance

在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;,最好没有像反射这样的技巧。

8 个答案:

答案 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}完成所有相同的事情。 }(AppleprintColor等。)有意义吗?从常规eatApple的转换之间没有任何变化的事情显然仍然相同。

答案 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

}