【发布时间】:2018-03-15 07:06:51
【问题描述】:
我正在阅读关于 Wizards and Warriors 的 Eric Lippert 博客。有趣的阅读,但我发现某些部分难以理解(不是作者的错,我只是 OOP 的初学者)。
他提出了一个游戏中两种角色类型的问题,一个巫师和一个战士,规则是:
- 战士只能使用剑。
- 法师只能使用法杖
在博客中,他在第一部分使用getter/setter 来处理角色的武器,但我们将其更改为库存系统。所以,我们有一个名为 Player 的 abstract class 和一个项目列表 (ArrayList)。
interface Weapon {
attack(Enemy enemy);
}
public class Staff implements Weapon {}
public abstract class Player {
private List<Weapon> weaponInventory;
//left out constructor and other methods to keep it on point
abstract void add(Weapon add)
}
并像这样使用它:
public class Wizard extends Player {
@Override
public void add(Weapon add){
//code to add weapon;
}
}
您将如何构造 add 方法来强制执行向导只能使用五线谱的规则?我想过在武器上打电话给getClass() 或getType(),但这些都被认为是不好的做法。
我能想到的最佳答案是有一个名为 type 的 String 变量,以及在 Weapon interface 中的 getter。在对象构造期间,将类型设置为剑或法杖。但是,这并没有真正的帮助,因为您可以创建一个剑对象,将工作人员作为类型传入,然后使用它。
你会如何防止剑被添加到巫师的库存中?
【问题讨论】:
-
这在很大程度上取决于您的设计。如果您希望在编译时完成检查,那么答案之一中建议的泛型会有所帮助。然而,在更现实的设计中,您很少将
Staff显式地赋予Wizard。相反,您将Weapon提供给Player。所以检查必须在运行时完成,泛型在这里无济于事。所以在不知道你的设计的情况下很难给你答案 -
@AdrianShum - 假设运行时
-
刚刚快速浏览了这篇文章,作者正在考虑编译时...
-
@AdrianShum - 在这种情况下不喜欢使用泛型。对于我的问题,我想知道如何在运行时防止巫师将剑添加到库存中。他使用 getter/setter,但实际上您将使用系统(列表、字典等)之类的库存
-
@AdrianShum - 这不会带来对客户过于信任的问题吗?是什么阻止他们在 Sword 构造函数中放置 WeaponType.Staff?除非你自己做,即客户端没有设置它,你在构造函数中私下做。