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

发布于 2024-12-08 03:11:49 字数 298 浏览 2 评论 0原文

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

public abstract class Entity
{

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

    protected abstract void entityInit();
}

这是怎么回事?当它调用 entityInit() 时会发生什么?

I'm looking over some code in a game and I came across something that I haven't seen before and I don't really know whats going on.

public abstract class Entity
{

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

    protected abstract void entityInit();
}

What's going on here? What happens when it calls on entityInit()?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

烂人 2024-12-15 03:11:49

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

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

An abstract class is never instantiated. Only its concrete subclasses can be instantiated. So, when the concrete subclass (let's call it Foo) constructor is called, it calls super(world). The Entity constructor then calls entityInit(), which has been overridden by Foo. It thus calls the Foo entityInit concrete method.

Note that this is bad practice, because the entityInit method will be called on a not yet fully constructed object. The subclass thus has to make sure this method doesn't access any field it might declare, because they will all be unititialized.

无需解释 2024-12-15 03:11:49

所发生的情况是,entityInit() 的具体子类实现被调用。由于 Entity 是抽象的,因此只能从具体子类的构造函数调用它的构造函数,该子类的构造函数必须具有 entityInit() 的实现。

从抽象类的代码中调用抽象方法实际上是非常常见的,并且几乎是抽象方法的全部要点。另请参阅模板方法模式

但是,从构造函数调用抽象方法(如本例所示)是有问题,应该避免,主要是因为抽象方法将在未完全初始化的对象上运行,因此可能处于不一致的状态。具体来说,entityInit() 的实现将在定义它的类的构造函数之前运行。

What happens is that the concrete subclass's implementation of entityInit() gets called. Since Entity is abstract, its constructor can only ever be called from a concrete subclass's constructor, which must have an implementation of entityInit().

Calling abstract methods from within code of the abstact class is actually perfectly common, and pretty much the entire point of abstract methods. See also the template method pattern.

However, calling abstract methods from a constructor as in this case is problematic and should be avoided, mainly because the abstract method will run on an object that is not completely initialized and thus possibly in an inconsistent state. Specifically, the implementation of entityInit() will run before the constructor of the class it's defined in.

余厌 2024-12-15 03:11:49

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

Well, mostly, this is used in Template Method pattern. The subclassed, non-abstract class of Entity will implement the entityInit() method. These subclasses implement the way their entityInit() must be defined for that class.

In Wikipedia, it says....

In object-oriented programming, first a class is created that provides
the basic steps of an algorithm design. These steps are implemented
using abstract methods. Later on, subclasses change the abstract
methods to implement real actions. Thus the general algorithm is saved
in one place but the concrete steps may be changed by the subclasses.

In your case, you won't worry about subclasses having to entityInit() itself, as the constructor will do this by default:

Example:

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);
    }
}
送舟行 2024-12-15 03:11:49

好吧,没什么。

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

Well, nothing.

Unless a concrete class implements the abstract method entityInit, you won't be able to create an Entity class that will use the method.

榕城若虚 2024-12-15 03:11:49

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

您不能创建抽象类的实例,而具体类(您可以创建其实例)不得具有抽象方法。所以一切都很好。

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

示例(基于您的班级):

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

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

虽然该示例没有多大逻辑意义,但它应该说明这一点。
首先将调用 Entity 构造函数,该构造函数又调用 entityInit()。但是,由于 Person 的初始化块尚未运行,因此 name 仍然为 null。

Since you need to create a concrete subclass anyways you need to implement entityInit() as well. That method will then be called.

You can't create instances of abstract classes and concrete class (which you can create instances of) must not have abstract methods. So everything is fine.

One note: be aware that if you access fields defined in the subclass, accessing them in entityInit() might result in a NullPointerException since they might not be initialized.

Example (based on your class):

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

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

Although that example doesn't make much logical sense, it should illustrate the point.
First the Entity constructor will be called, which in turn calls entityInit(). However, since the initializer block of Person has not run yet, name is still null.

不即不离 2024-12-15 03:11:49

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

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

it's a common practice. You use the abstract method in a top level method, implementors will only need to implement the abstract, so logic will be left in base class.

Sorry haven't noticed it was a constructor... pretty strange in that position....

古镇旧梦 2024-12-15 03:11:49

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

另一种说法是不要让this从构造函数主体中逃逸

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

Don't call abstract/virtual methods from the constructor. it would call the concrete subclass implementation. But the concrete subclass's member variables would have not initialized.

Another way to say that don't let your this escape from the constructor body.

But in this particular case, the whole purpose of the method is to initialize the members of the this object. So it's fine. but with this approach, we have to chain the method invocation of super class( if it has the implementation ).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文