当创建两个或多个类的引用时,可销售菜单工具包字段会更改(使用GitHub)

Tha*_*tis 9 java minecraft bukkit

我最近在我的Spigot/Bukkit插件中遇到了一个奇怪的错误,完全没有任何意义.请注意,这个问题可能很长,因为我正在处理的项目相当大,因为源代码(下面提供)包含不会包含在这里的类,我将尽力描述我的问题.

在Minecraft中,使用Bukkit API,您可以创建图形菜单(GUI),您可以在其中放置项目在某些插槽中,单击时,您可以调整功能.

在我的例子中,我创建了Menu基础类,其中包含创建此类菜单的基本方法.然后,PurchaseMenu扩展Menu类的用于触发特定位置的功能,以模拟可从菜单中单击的产品的事务.

在深度方面,我将包含的菜单包含"套件"显示(如游戏类),当一个左键单击显示器,玩家可以购买它,或者如果它已经购买,玩家将只选择该套件以供使用.当右键单击显示器时,播放器可以将套件升级到3.

在这两种情况下,都必须弹出一个交易菜单,以便购买或升级所点击的套件.我的设计非常简单,通过从每个PurchaseMenu类的构造函数传递单击的工具包.

以上所有问题都是套件从构造函数中正确传递,但实际购买或升级的套件是随机的(显然不是,但还没有找到任何证据),这通常发生在一些尝试.

我的设计:

  • 每个Menu类都包含两个方法.InventoryClick单击菜单显示(交互)时调用.InventoryConstruct在创建(打开)菜单时调用.
  • Purchase Menu类也包含两个方法.PurchaseProduct在成功购买显示器时调用.PrePaymentChecks是购买前需要进行的必要检查.

我的问题:

  • 如何修补该问题,并将正确的Kit保存在类的私有字段中?
  • 如何在某些项目中改进我的设计(方法)以避免此类问题?

任何形式的帮助表示赞赏,我希望我详细描述了我的问题,如果您需要任何进一步的源代码,请在下面发表评论.

更新

由于问题将超过30k字符,我将整个项目上传到Git存储库.

https://github.com/parat26/core

Menu.java:https://github.com/parat26/core/blob/master/src/src/ares/core/menu/Menu.java

PurchaseMenu.java:https://github.com/parat26/core/blob/master/src/src/ares/core/menu/PurchaseMenu.java

BattleOptionsMenu.java:https://github.com/parat26/core/blob/master/src/src/ares/core/menu/type/MenuBattleOptions.java

PurchaseMenuKit.java: https://github.com/parat26/core/blob/master/src/src/ares/core/menu/type/PurchaseMenuKit.java

AMD*_*MDG 2

尝试将 PurchaseMenu.object 更改为 Final 并查看输出是什么。还有,System.out.println()是你的朋友。

object我不建议您在套件中使用 Object,因为当您设置为时,它可能会更改对象sellableKit。创建一个名为 的接口Sellable<T>,以便您可以通过以下方式强制执行类型(称为强类型):

private final ItemStack item;
protected final Sellable<? super Kit> kit;
private final GoldCurrency currency;

public PurchaseMenu(String menuName, ItemStack sellableItem, Sellable<? super Kit> sellableKit, GoldCurrency currencyType)
{
    super(Material.STONE, menuName, 54);

    item = sellableItem;
    kit = sellableKit;
    currency = currencyType;

    DependOnEvents(true);
}
Run Code Online (Sandbox Code Playgroud)

将这些字段设置为最终字段也是一种很好的做法,因为您似乎不会在创建对象后设置这些字段,并且会让任何人立即知道这些对象永远不会更改。它还应该说明情况,因为最终对象无法更改。

由于您刚刚制作了对象的副本,因此应该删除该private Kit kit;字段。BuyKitOwnershipMenu你的PurchaseProduct()方法可以改为

@Override
    public void PurchaseProduct(GoldCurrency currency, Client client)
    {
        client.getManager().setKitOwned(kit, true);
    }
Run Code Online (Sandbox Code Playgroud)

由于套件现在受到保护并处于超类中。