4

ゲーム内のコードを調べていると、これまでに見たことのないものに出くわしましたが、何が起こっているのかよくわかりません。

public abstract class Entity
{

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

    protected abstract void entityInit();
}

何が起きてる?それが要求するとどうなりますentityInit()か?

4

7 に答える 7

9

抽象クラスがインスタンス化されることはありません。インスタンス化できるのは、具体的なサブクラスのみです。したがって、具象サブクラス(それを呼びましょうFoo)コンストラクターが呼び出されると、それは。を呼び出しますsuper(world)。次に、EntityコンストラクターはentityInit()、を呼び出します。これは、によってオーバーライドされていFooます。したがって、FooentityInit具象メソッドを呼び出します。

entityInitメソッドはまだ完全に構築されていないオブジェクトで呼び出されるため、これは悪い習慣であることに注意してください。したがって、サブクラスは、すべてが単一化されるため、このメソッドが宣言する可能性のあるフィールドにアクセスしないようにする必要があります。

于 2011-10-04T07:13:46.787 に答える
3

何が起こるかというと、具体的なサブクラスの実装entityInit()が呼び出されます。は抽象であるためEntity、そのコンストラクターは、の実装が必要な具象サブクラスのコンストラクターからのみ呼び出すことができますentityInit()

abstactクラスのコード内から抽象メソッドを呼び出すことは、実際には完全に一般的であり、抽象メソッドのほとんどすべてのポイントです。テンプレートメソッドパターンも参照してください。

ただし、この場合のようにコンストラクターから抽象メソッドを呼び出すことは問題があり、避ける必要があります。これは主に、抽象メソッドが完全に初期化されていないため、一貫性のない状態で実行されるためです。具体的には、の実装は、でentityInit()定義されているクラスのコンストラクターの前に実行されます。

于 2011-10-04T07:11:09.770 に答える
2

まあ、ほとんどの場合、これはテンプレートメソッドパターンで使用されます。のサブクラス化された非抽象クラスはEntity、メソッドを実装しentityInit()ます。これらのサブクラスは、entityInit()そのクラスに対して定義する必要がある方法を実装します。

ウィキペディアでは、それは...と言います。

オブジェクト指向プログラミングでは、最初に、アルゴリズム設計の基本的な手順を提供するクラスが作成されます。これらの手順は、抽象メソッドを使用して実装されます。後で、サブクラスは実際のアクションを実装するために抽象メソッドを変更します。したがって、一般的なアルゴリズムは1つの場所に保存されますが、具体的な手順はサブクラスによって変更される場合があります。

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);
    }
}
于 2011-10-04T07:19:22.717 に答える
1

まあ、何も。

具象クラスが抽象メソッドを実装しない限り、メソッドを使用するクラスentityInitを作成することはできません。Entity

于 2011-10-04T07:10:01.443 に答える
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まだnullです。

于 2011-10-04T07:10:07.723 に答える
1

それは一般的な習慣です。最上位メソッドでabstractメソッドを使用します。実装者は抽象を実装するだけでよいため、ロジックは基本クラスに残ります。

申し訳ありませんが、それがコンストラクターであることに気づいていません...その位置ではかなり奇妙です...。

于 2011-10-04T07:10:07.697 に答える
0

コンストラクターから抽象/仮想メソッドを呼び出さないでください。具体的なサブクラスの実装と呼ばれます。ただし、具象サブクラスのメンバー変数は初期化されていません。

別の言い方をすれば、これをコンストラクター本体から脱出させないでください

ただし、この特定のケースでは、メソッドの全体的な目的は、thisオブジェクトのメンバーを初期化することです。だから大丈夫です。ただし、このアプローチでは、スーパークラスのメソッド呼び出しをチェーンする必要があります(実装がある場合)。

于 2011-10-04T07:12:21.500 に答える