我有一个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)调用超级结构(我不希望他们必须决定应该调用哪些方法)
这可能吗?
答案 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时会发生什么?
Der()
被称为Base()
被称为Base.s
已初始化foo()
被称为Der.foo()
Der.foo
来电o.someOtherMethod
此时Der.o
为null
,您获得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实现。
您可以查看参考文献。