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);

而且我知道覆盖每个子类中的任何父 setter 函数都会起作用:

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中奇怪重复出现的模板模式的一次勇敢尝试。问题是您混合了泛型和原始类型,这意味着您没有“关闭模式的循环”。例如您的声明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 回答