我正在看游戏中的一些代码,我遇到了一些我以前没有见过的东西,我真的不知道发生了什么。
public abstract class Entity
{
public Entity(World world)
{
// irrelevent code
entityInit();
}
protected abstract void entityInit();
}这里发生了什么事?当它在entityInit()上调用时会发生什么
发布于 2011-10-04 15:13:47
抽象类永远不会实例化。只能实例化它的具体子类。因此,当具体的子类(让我们称其为Foo)构造函数被调用时,它将调用super(world)。然后,实体构造函数调用已被Foo覆盖的entityInit()。因此,它调用Foo entityInit具体方法。
请注意,这是一种不好的做法,因为将在尚未完全构造的对象上调用entityInit方法。因此,子类必须确保此方法不会访问它可能声明的任何字段,因为它们都将被初始化。
发布于 2011-10-04 15:11:10
具体的子类的entityInit()实现会被调用。因为Entity是抽象的,所以它的构造函数只能从具体的子类的构造函数中调用,而这个构造函数必须有entityInit()的实现。
从abstact类的代码中调用抽象方法实际上是非常常见的,而且几乎就是抽象方法的全部要点。另请参阅template method pattern。
但是,从构造函数调用抽象方法是problematic and should be avoided,这主要是因为抽象方法将在未完全初始化的对象上运行,因此可能处于不一致的状态。具体地说,entityInit()的实现将在定义它的类的构造函数之前运行。
发布于 2011-10-04 15:19:23
大多数情况下,这是在Template Method pattern中使用的。Entity的子类、非抽象类将实现entityInit()方法。这些子类实现必须为该类定义其entityInit()的方式。
在维基百科上,它说...
在面向对象编程中,首先创建一个类,它提供算法设计的基本步骤。这些步骤是使用抽象方法实现的。稍后,子类将更改抽象方法以实现实际操作。因此,一般的算法保存在一个地方,但具体的步骤可能会被子类改变。
在您的例子中,您不必担心子类必须entityInit()自身,因为构造函数将在默认情况下执行此操作:
示例:
public class StrictEntity extends Entity {
public StrictEntity(World world) {
super(world); //This will call entityInit();
}
protected void entityInit() {
//Example, don't take it as genuine.
PropertyConfig.getInstance.setStrict(true);
}
}https://stackoverflow.com/questions/7644342
复制相似问题