派生类可以调用它们的abtract-father类的构造函数,这些类调用它们尚未实现的方法吗?

时间:2014-04-02 00:25:44

标签: java oop abstract-class super

我有一个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:如果标题没有反映出我想问的内容,请随意提出另一个标题!

3 个答案:

答案 0 :(得分:3)

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

请考虑以下事项:

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
  7. 此时Der.onull,您获得NullPointerException

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

答案 1 :(得分:2)

呀。通过虚方法调度,调用方法(甚至从超类型中调用this的方法,如本问题所示)调用派生类型的代码。

(编辑)

要将此与人们可能更熟悉的设置联系起来,请考虑

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

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

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

答案 2 :(得分:2)

- >这可能吗?

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

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

参考您的代码,层次结构为:

   DarthVader
        │
       ─┴─
      │   │
    Jedi Sith

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

多态性是指您使用指向实现类对象的抽象引用。像这样:

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

对于JVM,它将正确调用Jedi中的method1()。这个概念叫做Dynamic dispatch。在现代语言中,它由vTable实现。

您可以查看参考文献。