方法重载:最佳使用方法



我有这些接口:

public interface IShipOwner {}
public interface ICitizen {}
public interface IPlayer extends ICitizen, IShipOwner {}
public interface IAIPlayer exends IPlayer {}

此外,我在同一类中有这两个方法:

public boolean isHumanPlayer(ICitizen citizen) {
    if (citizen instanceof IPlayer) {
        if (citizen instanceof IAIPlayer) {
            return false;
        } else {
            return true;
        }
    }
    return false;
}
public boolean isHumanPlayer(IShipOwner shipOwner) {
    if (shipOwner instanceof IPlayer) {
        if (shipOwner instanceof IAIPlayer) {
            return false;
        } else {
            return true;
        }
    }
    return false;
}

当使用类型 IPlayer 的对象调用 isHumanPlayer 时,我必须将其转换为类型 ICitizenIShipOwner 以明确应调用哪个方法。

从客户端的角度来看,调用这些方法的最佳方法是什么?如果可能的话,我确实希望避免在保留方法重载的同时强制转换参数的需要。

  1. 让公民实施IShipOwner即使不是每个IShipOwner都是ICitizen,反之亦然。
  2. 使用不同的方法名称。
  3. 我没有想到的其他事情。

测试对象的功能是一种代码异味。 这意味着您没有使用语言中内置的OO功能。 您可能应该完全摆脱isHumanPlayer方法。 然后,无论您在哪里测试isHumanPlayer并根据结果执行不同的操作,只需在IPlayer上调用一个方法,该方法根据实现执行不同的操作。

我的建议:

  • interface Player - 常见行为在这里,包括基于isHumanPlayer值执行任何操作的方法。
  • interface HumanPlayer extends Player - 添加仅与人类玩家相关的方法。
  • interface AiPlayer extends Player - 添加仅与 AI 玩家相关的方法。

HumanPlayerAiPlayer添加的方法应仅由程序中专门将玩家视为人类或 AI 玩家的部分调用。 你很少会觉得有必要投射。 如果这样做,则可能需要在层次结构中向上移动对强制转换对象调用的方法。

根据您描述的现有层次结构,听起来人类和 AI 玩家都是ShipOwner。 但是ShipOwner接口的确切位置取决于是否有任何其他类型的Player不是ShipOwner,或者任何类型的ShipOwner不是Player

我赞同Kevin Krumwiede的观点。

但是如果你真的必须保持isHumanPlayer(),那么:

让公民实现IShipOwner,即使不是每个IShipOwner都是ICitizen,反之亦然。

不。 从不。 "如果你去了,你只会找到痛苦。">

使用不同的方法名称。

那行得通,但等于认输,对吧?

我没有想到的其他事情。

这给我们带来了:

  • 添加isHumanPlayer( IPlayer player )

  • 想出一个新的接口,它由所有其他接口扩展,也许IPerson

  • isHumanPlayer()每个界面的一部分。 因此,人类玩家只需返回true;其他人只会返回false.

另外请注意,这整个混乱:

public boolean isHumanPlayer(ICitizen citizen) {
    if (citizen instanceof IPlayer) {
        if (citizen instanceof IAIPlayer) {
            return false;
        } else {
            return true;
        }
    }
    return false;
}

可以重述如下:

public boolean isHumanPlayer(ICitizen citizen) 
{
    return citizen instanceof IPlayer && !(citizen instanceof IAIPlayer);
}

(这可能是也可能不是你的初衷。

最新更新