在超类中调用子类方法

时间:2016-06-06 18:42:39

标签: java

我的项目包含一些遗留代码。它有两个不同包中具有相同名称的控制器。

例如:org.a.TestControllerorg.b.TestController

我在子类中创建了sayHello()方法,如下所示。

package org.b;

public class TestController extends org.a.TestController{

    public String sayHello(){ return "hello"; }

}

我在Base类中访问sayHello()方法,但我感到困惑,这是访问基类中子类方法的最佳方法。 每个控制器包含5k行代码和一些静态方法。我试过以下两种方式。

  1. String s = new org.b.TestController().sayHello();
  2. String s = ((org.b.TestControlle)this).sayHello();
  3. 请告诉我上述两种方式有什么区别,哪种方式最好? 如果我做错了,请纠正我。

3 个答案:

答案 0 :(得分:0)

您列出的两种方式是对不同的对象执行相同的调用:

  • new org.b.TestController().sayHello();创建一个新的TestController对象,
  • ((org.b.TestController)this)使用this个对象进行通话。仅当this实际上是org.b.TestController或其子类之一时,这才会成功;否则,将抛出强制转换异常。

虽然结果是相同的,因为sayHello()没有引用与对象关联的任何状态(即它没有引用对象的任何字段),但操作根本不同。

注意:在子类中重写的超类的任何非私有非静态方法都会从子类调用该版本,无论调用它的位置如何。例如

class A {
    public void print() { System.out.println("Hello");}
    public void sayHello() { print(); }
}
class B extends A {
    public void print() { System.out.println("Hello, world!");}
}
...
B b = new B();
b.sayHello();

打印"Hello, world!",即使sayHello在超类中调用print

答案 1 :(得分:0)

好的,我将在这个答案中做出一些假设。

  1. 你有一个课程Base,你正在做一些逻辑。让我们称之为Base#logic()
  2. 您有Base - org.a.TestControllerorg.b.TestController
  3. 的子类
  4. BaseTestController都实施String sayHello()
  5. 然后Base#logic()就像这样:

    void logic() {
        String s = this.sayHello();
        // ...
    }
    

    那是因为默认情况下会调用类型层次结构中最低的方法。你不需要明确地做任何事情。只需确保Base实现sayHello()或者是一个定义为public abstract String hello();的抽象类。

答案 2 :(得分:0)

只保证第一行有效。您的父类可以,但不必是子类的实例。假设您有A类和B类扩展A.在B类中,您有一个方法,例如methodB()。可以这样做:

A a = new B();
((B)a).methodB();

在这种情况下它会起作用。但如果你这样做

A a = new A();
((B)a).methodB(); //Runtime ClassCastException will be thrown

因为在这种情况下你的实例a不是B的实例,因此不知道方法B是什么。但是,如果你的代码中的任何地方(无论哪个类别)都可以

new B().methodB();

它将始终有效,因为您刚刚创建了B类的新实例并调用了自己的方法。关键是父母不知道他的孩子有什么额外的方法,而孩子们总是知道父母有什么(父母的私人方法除外)。如果在你的B班你将使你的方法B静态,那么你当然不需要实例化B的新实例而且可以做到

B.methodB();