【问题标题】:Calling superclass method in superclass在超类中调用超类方法
【发布时间】:2012-12-30 17:57:49
【问题描述】:

我找不到一个好的总结来描述我的问题(欢迎提出建议)

我有以下两个课程:

测试1

import java.lang.reflect.Method;

abstract class Test1 {

    boolean condition = true;

    public void f() {
        System.out.println("Test1 : f");
    }

    public void g() {
        System.out.println("Test1 : g");
        f();
        if (condition) {
            f(); // call Test1.f() here. HOW?

            // Following didn't work
            try {
                Method m = Test1.class.getDeclaredMethod("f");
                m.invoke(this);
            } catch (Exception e) {
                System.err.println(e);
            }
        }
    }
}

测试2

class Test2 extends Test1 {

    public void f() {
        System.out.println("Test2 : f ");
    }

    public static void main(String[] args) {
        Test2 t2 = new Test2();
        t2.g();
    }

}

输出是:

Test1 : g
Test2 : f
Test2 : f
Test2 : f

问题是由于Test1中的condition字段给出的一些特殊条件,我想在g()中调用Test1f(),即使我使用Test2的对象进行调用.

我尝试了反射,但它也不起作用。有什么建议吗?

编辑 1: 我没有具体提到它,但如果你仔细看Test1是抽象的。所以我不能创建它的对象。

【问题讨论】:

    标签: java inheritance overriding subclass superclass


    【解决方案1】:

    您应该认真考虑您尝试构建的逻辑。您试图覆盖子类中的方法 f 的原因肯定是有原因的。

    或者,您可以将布尔值作为方法 f 的返回值,并在子方法中使用 boolean r = super.f(); if(r){//execute child logic.} 这应该可以解决您的问题。

    【讨论】:

    • 逻辑很复杂,没错。但我不明白你的意思,super.f() 返回void,这不能分配给布尔值。
    • 我建议将 void 更改为布尔值。这将有助于决定子方法逻辑的执行。
    • 是否调用父级的逻辑来自g()的内部逻辑。它可能不适用于所有对f() 的调用(例如来自h() 的调用)。
    【解决方案2】:

    我的理解。

    您的问题:
    如果g()Test1 类中调用方法f() 那么为什么它运行子(Test2)类的f()

    答案:来自JLS-8.4.8.1

    子类 Test2 声明了一个方法 f(),它覆盖了 Test1 的方法 f()。它从类 Test1 继承方法 g()

    本例中关于覆盖的关键点在于类Test1中声明的方法g()调用了当前对象this定义的f()方法,不一定是f()方法在 Test1 类中声明。

    因此,当使用Test2对象t2在main中调用g()时,g()方法体中f()的调用是对象t2的f()的调用。这允许 Test1 的子类更改 f() 方法的行为,而无需重新定义它。

    脑震荡:

    因此,如果某个类重写了其父类的某些方法,则契约说,Test1 旨在扩展,应该清楚地表明类与其子类之间的契约是什么,并且应该清楚地表明子类可以重写 @ 987654338@这个方法。

    【讨论】:

      【解决方案3】:

      在Test1中添加一个方法f2:

      private void f2() {
          System.out.println("Test1 : f");
      }
      public void f() {
          this.f2()
      }
      

      这样你就可以在条件为真时调用 f2()。

      【讨论】:

        【解决方案4】:

        如果方法名称相同,则不能这样做。
        其他方式也可以直接在子类中使用super.f()调用超类方法。

        【讨论】:

          【解决方案5】:

          UPD:专门针对那个不太专心的人,我正在给 解释。

          在下面的代码中,我正在使用方括号 { } 创建新的 anonymous 类。这允许我创建子类Test1 的新实例。


          除了使用reflection,你还可以做这样有趣的事情:

          public void g() {
              System.out.println("Test1 : g");
              f();
              if (condition) {
                   new Test1(){}.f();
              }
          }
          

          唯一的缺点是f()方法调用这种方式是调用绝对另一个对象的方法。

          【讨论】:

          • Test1 是抽象的,所以我无法创建它的对象。
          • @Xolve, new Test1(){} 它是一个使用匿名类创建的对象。所以,我可以。
          • @Xolve,可能你没注意到,new Test1() 后面有{} 括号。
          • @Andremoniy 我们不知道Test1 抽象化的原因,可能还有其他方法需要您实现。
          • @GaborSch 我们正在讨论这个特殊情况。顺便说一句,我 +1 您的答案,在通常情况下,您的解决方案当然更好。我的答案只是使用反射的替代方法。
          【解决方案6】:

          继承只允许你继承super.f()的行为,覆盖它@Override或两者都

          @Override
          public void f(){
              super.f(); 
              //do something  
          }
          

          您不能覆盖一个方法,然后在它被覆盖之前尝试调用父方法状态。继承不是这样工作的。

          【讨论】:

            猜你喜欢
            • 2021-11-10
            • 2011-03-28
            • 1970-01-01
            • 2011-03-02
            • 1970-01-01
            • 2020-05-27
            • 1970-01-01
            • 2015-04-20
            • 1970-01-01
            相关资源
            最近更新 更多