抽象类正在使用它自己的抽象方法?

时间:2011-10-04 07:05:54

标签: java abstract-class abstract abstract-methods

我正在查看游戏中的一些代码,我遇到了一些我以前从未见过的东西,我真的不知道发生了什么。

public abstract class Entity
{

    public Entity(World world)
    {
        // irrelevent code
        entityInit();
    }

    protected abstract void entityInit();
}

这里发生了什么?当它呼叫entityInit()时会发生什么?

7 个答案:

答案 0 :(得分:7)

从不实例化抽象类。只能实例化其具体的子类。因此,当调用具体子类(让我们称之为Foo)构造函数时,它会调用super(world)。然后,实体构造函数调用entityInit(),该Foo已被entityInit覆盖。因此它调用了Foo entityInit具体方法。

请注意,这是不好的做法,因为{{1}}方法将在尚未完全构造的对象上调用。因此,子类必须确保此方法不会访问它可能声明的任何字段,因为它们都将被整体化。

答案 1 :(得分:3)

会发生什么事情,调用具体子类的entityInit()实现。由于Entity是抽象的,因此只能从具体子类的构造函数中调用其构造函数,该构造函数必须具有entityInit()的实现。

从abstact类的代码中调用抽象方法实际上是非常常见的,而且几乎是抽象方法的全部要点。另请参阅template method pattern

但是,在这种情况下从构造函数调用抽象方法是problematic and should be avoided,主要是因为抽象方法将在未完全初始化的对象上运行,因此可能是不一致的州。具体来说,entityInit()的实现将在它定义的类的构造函数之前运行。

答案 2 :(得分:2)

嗯,大多数情况下,这用于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);
    }
}

答案 3 :(得分:1)

嗯,没什么。

除非具体类实现抽象方法entityInit,否则您将无法创建将使用该方法的Entity类。

答案 4 :(得分:1)

因为你需要创建一个具体的子类,你还需要实现entityInit()。然后将调用该方法。

您无法创建抽象类的实例,具体类(您可以创建实例)必须没有抽象方法。所以一切都很好。

注意:请注意,如果访问子类中定义的字段,则在entityInit()中访问它们可能会导致NullPointerException,因为它们可能未初始化。

示例(基于您的班级):

class Person extens Entity {
   private String name = "Player";

   protected void entityInit() {
     int nameLen = name.length(); //NPE here!!!
   }
}

虽然这个例子没有太大的逻辑意义,但它应该说明一点。 首先调用Entity构造函数,然后调用entityInit()。但是,由于Person的初始化程序块尚未运行,name仍然为空。

答案 5 :(得分:1)

这是一种常见的做法。您在顶级方法中使用抽象方法,实现者只需要实现抽象,因此逻辑将保留在基类中。

很抱歉没有注意到它是一个构造函数......在那个位置上很奇怪......

答案 6 :(得分:0)

不要从构造函数中调用抽象/虚方法。它会调用具体的子类实现。但具体子类的成员变量尚未初始化。

另一种说法不要让你的这个从构造函数体中逃脱的方法

但在这种特殊情况下,该方法的整个目的是初始化this对象的成员。所以没关系。但是使用这种方法,我们必须链接超类的方法调用(如果它有实现)。