【问题标题】:Can derived classes call the constructor of their abtract-father classes, that call their not yet implemented methods?派生类可以调用它们的抽象父类的构造函数,调用它们尚未实现的方法吗?
【发布时间】:2014-04-02 00:25:44
【问题描述】:

我有一个 java 问题。我想创建一个具有一些抽象方法的抽象类。在抽象类构造函数中,我想调用这些抽象方法。

扩展这个抽象类的类必须实现抽象方法,它们唯一要做的就是在自己的构造函数中调用抽象类的构造函数(使用 super() 关键字)。

如果听起来有点复杂,这里是我想做的一个例子(如果有任何语法错误,我很抱歉,我在记事本中写了这个例子):

public abstract class DarthVader{

    public DarthVader() {
        System.out.println("Luke, I am your father!");

        method1();
        method2();
    }

    public abstract void method1();
    public abstract void method2(); 
}

...

public class Jedi extends DarthVader {

    public Jedi() {
        super();
    }

    public void method1() {
        System.out.println("I am a true jedi");
    }

    public void method2() {
        System.out.println("Prepare to die!");
    }
}

...

public class Sith extends DarthVader  {

    public Sith() {
        super();
    }

    public void method1() {
        System.out.println("Hello dad");
    }

    public void method2() {
        System.out.println("Sith Lords Rule!");
    }
}

所以,我希望子类的唯一责任是:

1) 抽象方法的实现

2) 调用超级构造器(我不希望他们必须决定应该调用哪些方法)

这可能吗?

  • PS:如果标题不能反映我想问的问题,请随时提出其他问题!

【问题讨论】:

标签: java oop abstract-class super


【解决方案1】:

这是允许的,但它存在严重的危险,一些编译器会给你一个警告。它与抽象的超类或抽象的方法无关。它与基类调用非最终方法有关。

考虑以下几点:

class Base {
  SomeObject s;
  Base() { s = new SomeObject(); foo(); }
  void foo() { s.someMethod(); }
}

class Der {
  SomeOtherObject o;
  Der() { super(); o = new new SomeOtherObject();}
  @Override foo() { o.someOtherMethod(); }
}

创建 Der 时会发生什么?

  1. Der() 被调用
  2. Base() 被称为
  3. Base.s 已初始化
  4. foo() 被调用
  5. 呼叫已发送至Der.foo()
  6. Der.foo 致电o.someOtherMethod

此时Der.onull,你得到一个NullPointerException

(构造函数中的虚拟成员调用)[构造函数中的虚拟成员调用对主题有很好的解释。它适用于C#,但也适用于java

【讨论】:

    【解决方案2】:

    ->这可能吗?

    是的,当然。只要您的子类实现所有抽象方法。

    其实这是Polymorphism的概念:多态是为不同类型的实体提供单一接口。

    参考你的代码,层次结构是:

       DarthVader
            │
           ─┴─
          │   │
        Jedi Sith
    

    在 DarthVader 中,您声明了两个抽象方法:method1()method2()。然后在子类中实现它们。

    多态是你使用抽象引用来指向一个实现类对象。像这样:

    DarthVader j = new Jedi();
    j.method1();
    

    对于 JVM,它会在 Jedi 中正确调用 method1()。这个概念被称为Dynamic dispatch。在现代语言中,它由vTable 实现。

    你可以看看参考资料。

    【讨论】:

      【解决方案3】:

      是的。通过虚拟方法分派,调用方法(甚至从超类型调用this 的方法,如本题)会调用派生类型的代码。

      (编辑)

      要将其与人们可能更喜欢的环境联系起来,请考虑

      List a = new ArrayList();
      int n = a.size();
      

      .size() 调用ArrayList 的实现——即使a 被声明为List,它在运行时也是ArrayList

      在抽象类的构造函数中,this(隐式)声明为DarthVader,但在运行时,它可以是派生类型的实例(在这种情况下,它必须是,因为@987654330 @ 是抽象的)。因此method1()method2() 成功。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-06
        • 2018-07-16
        相关资源
        最近更新 更多