【问题标题】:Designing an item inventory system for a game and having issues为游戏设计物品库存系统并遇到问题
【发布时间】:2013-09-24 19:17:34
【问题描述】:

我一直在研究一个小型库存系统,只是为了练习我的 OO 编程。我在 Netbeans 中使用 Java 7。

玩家将拥有一个物品栏(基础项目类的 ArrayList),所有创建的项目都将是该基础项目类的子项。

任何项目都不应该是 BaseItem 类型,它们都会从该类型扩展,所以据我了解,BaseItem 类应该是抽象的?

public abstract class BaseItem {
    protected GoldValue itemValue;
    protected String itemName;

    //accessors and mutators down here
}

子项类型也将具有不同的属性,我打算将其实现为接口,例如 Stackable、Consumable 等。

界面看起来像这样

public interface Stackable {   

    public void stack (StackableItem bi1);

}

如您所见,我在这里引用了 StackableItem,它是 BaseItem 的子项之一,它也是抽象的,具体项目将由它构建。

public abstract class StackableItem extends BaseItem implements Stackable{

    protected int quantity;
    protected int maxStacks;

    @Override
    public void stack (StackableItem si)
    {
        if(this.getQuantity() + si.getQuantity() < maxStacks){
            this.setQuantity(this.getQuantity()+si.getQuantity());
            si.setQuantity(0);
        }
        else if(this.getQuantity() + si.getQuantity() > maxStacks){
            int diff = maxStacks - this.getQuantity();
            this.setQuantity(this.getQuantity() + diff);
            si.setQuantity(si.getQuantity() - diff);
        }
    }
}

这是一个特定项目的示例:

public class StackableItemExample extends StackableItem{

    public StackableItemExample ()throws GoldException
    {
        this(new GoldValue(0,0,0), "unnamed", 1);
    }
    public StackableItemExample(GoldValue gv, String name, int quan) throws GoldException
    {
        this.itemValue = gv;
        this.itemName = name;
        this.quantity = quan;
        this.maxStacks = 10;
        this.itemValue.setGoldValue(gv.getGold()*quan, gv.getSilver()*quan, gv.getCopper()*quan);
    }


}

我的InventoryBaseItem 对象中的ArrayList,允许将StackableItemExample 对象插入其中没有问题。问题是,我的库存系统不能说BaseItem.stack(),因为父母不知道这种方法。

我想制作一个非常容易扩展的项目系统,通过实现和扩展预先创建的类和接口,可以非常简单地创建一个新项目,但这妨碍了我。

【问题讨论】:

    标签: java inheritance interface polymorphism abstract


    【解决方案1】:

    任何项目都不应该是 BaseItem 类型,它们都会从它扩展而来,所以据我了解,BaseItem 类应该是抽象的?

    我觉得不错


    如果你想让BaseItem.stack() 工作,你至少可以做两件事:

    • stack() 移动到您的基类中,并为其提供什么都不做的默认实现。然后在您的 StackableItem 类中覆盖它,或者
    • 使用instanceof 查看 BaseItem 是否为 StackableItem,然后将其转换为 StackableItem 并从那里开始。

    第二种方法如下所示:

    BaseItem item = YourList.get(i);
    if(item instanceof StackableItem){
        StackableItem stackable = (StackableItem)item;
        stackable.stack()  /* Now works without issue */
    }
    

    【讨论】:

    • 我会试一试,但是有没有可能在铸造过程中丢失一些数据?我要问的是,item 是否仍然具有 StackableItem 类的值,但在使用 Item. 或 Item.() 时不可见?如果是这样,那就完美了!
    • 是的,这正是它的工作原理(不,不会丢失任何数据)。您不会丢失有关该对象的附加信息——它的运行时类型仍然是您创建的任何内容。除非您首先将其转换为适当的子类,否则您无法访问这些成员/方法。
    • 太棒了,这应该可以完美运行。这样做有什么警告吗?类型转换一个对象看起来确实很冒险,但是只要我们使用 instanceof 就可以了?
    • Java 中的铸造比其他语言“更安全”。列出的代码是处理具有基本类型对象集合并希望对各种子类提供的附加功能进行操作的情况的常用方法。并且instanceof 保护您免受ClassCastExceptions。
    【解决方案2】:

    使每个物品都可堆叠 - 当前不可堆叠的物品的堆叠尺寸应为 1。然后,您可以摆脱可堆叠的抽象类和接口,将该功能放入基类中。

    【讨论】:

    • 不幸的是,这种类型的实现可能不适用于其他项目属性,例如可食用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-17
    • 1970-01-01
    • 1970-01-01
    • 2011-10-16
    • 1970-01-01
    • 2018-01-02
    • 1970-01-01
    相关资源
    最近更新 更多