2

2Dゲームエンジンに流暢なインターフェイスを実装しようとしています。

私の実装の簡略化された例:

public class Sprite<T> {

    protected float x = 0.0;
    protected float y = 0.0;

    public T setPosition(float x, float y) {
        this.x = x;
        this.y = y;
        return (T)this;
    }

}

public class Living<T extends Living> extends Sprite<Living> {

    protected boolean alive = false;

    public T setAlive(boolean alive) {
        this.alive = alive;
        return (T)this;
    }

}

public class Entity<T extends Entity> extends Living<Entity> {

    protected String name = null;

    public T setName(String name) {
        this.name = name;
        return (T)this;
    }

}


Entity entity = new Entity().setPosition(100, 200).setAlive(true).setName("Zombie");

「関数setAlive(boolean)が存在しません。」というエラーが表示され続けます。

私のメソッドを逆に(より論理的な順序で)使用すると、次のように機能します。

Entity entity = new Entity().setName("Zombie").setAlive(true).setPosition(100, 200);

そして、すべての子クラスの親セッター関数を上書きすると機能することを私は知っています。

public class Entity extends Living {

    protected String name = null;

    public Entity setPosition(float x, float y) {
        return (Entity)super.setPosition(x, y);
    }

    public Entity setAlive(boolean alive) {
        return (Entity)super.setAlive(alive);
    }

    public Entity setName(String name) {
        return (Entity)super.setName(name);
    }

}

しかし、私は「エンドユーザー」のためにインターフェースをできるだけ自由で複雑にせず、コードをできるだけコンパクトでクリーンなものにしたいと思っています。

ジェネリックを台無しにしただけなのか、ホールアプローチが完全に間違っているのかはわかりません。お役に立てば幸いです。どんなアドバイスも受け付けています。(私の悪い英語でごめんなさい。)

編集: 私はすでに次のアプローチをテストしました、そしてそれはEntityクラスのために働きます。

public class Sprite<T> {
...
}

public class Living<T> extends Sprite<T> {
...
}

public class Entity extends Living<Entity> {
...
}

Sprite&Livingもインスタンス化する必要があることを忘れました。例えば:

Living living = new Living().setPosition(50, 50).setAlive(false);
4

2 に答える 2

2

これは、 Javaで不思議なことに繰り返されるテンプレートパターンに対する勇敢な試みです。問題は、ジェネリックスとraw型を混合していることです。つまり、パターンの「ループを閉じている」わけではありません。たとえば、次の宣言Living

public class Living<T extends Living> extends Sprite<Living>

本当にあるべきです:

public class Living<T extends Living<T>> extends Sprite<T>

ある時点で、解決する「リーフ」クラスを宣言する必要があります。Tそうしないと、生の型またはワイルドカード(パターンの目的を損なう)に頼らずに、これらの型の変数をインスタンス化して宣言することができません。例えば:

public final class ConcreteEntity extends Entity<ConcreteEntity>

このパターンの実装の詳細については、ここで私の回答を参照してください。

于 2012-12-11T01:31:09.697 に答える
0

クラスモデルは非常に複雑だと思います。ジェネリックパラメーターを子クラスに渡して、明示的に宣言することができます。

public class Sprite<T> {
...
}

public class Living<T> extends Sprite<T> {
...
}

public class Entity extends Living<Entity> {
...
}
于 2012-12-11T01:34:45.907 に答える