在不了解条件函数的更多细节的情况下,您有两个选择。
一,你可以做类似的事情
if (f.GetType() == typeof(FireBall))
{
fireBall = (FireBall)f;
fireBall.FireTheFireBall();
}
else if (f.GetType() == typeof(Heal))
...
或者,您的 Ability 可以有一个抽象的 Activate 方法,所有派生类都需要重载该方法:
class Fireball
{
public override void Activate()
{
//do fireball specific things
this.FireTheFireBall();
}
public void FireTheFireBall() {...}
}
class Heal
{
public override void Activate()
{
//do healing specific things
this.ApplyTheBandage();
}
...
}
abstract class Ability
{
public abstract void Activate();
}
void condition(Ability f){
f.Activate(); //runs the version of Activate of the derived class
}
然后任何与能力一起工作的东西都可以调用 someAbility.Activate() 并且派生类提供的实现将被执行。
您还应该学习接口,它有点像抽象类。接口的好处是您可以实现多个接口,而您只能从一个基本抽象类继承。考虑一个具有转动和拉动功能的 IKnob 界面。您可能有一个实现 IKnob 的 Drawer 类、一个 Door 类、一个实现 Turn 并激活陷阱的 TrappedDoor 类。玩家走到一扇门前,按下门上的 Use 按钮,然后将对象 Open(IKnob 旋钮)传递给 open 函数
void Open(IKnob knob)
{
knob.Turn();
knob.Pull();
}
class TrappedDoor:IKnob,IMaterial,ISomethingElse,IHaveTheseOtherCapabilitiesAsWell
{
private bool TrapAlreadySprung{get;set;}
//more complex properties would allow traps to be attached either to the knob, or the door, such that in one case turning the knob activates the trap, and in the other, Pull activates the trap
public Turn() {
if(! TrapAlreadySprung)
{
MessageBox("You hit your head, now you're dead");
}
}
}
有一些方法可以检查某物是否有接口,因此如果某个玩家走到一个物品前并尝试与它交谈,您可以检查该对象是否具有 ICanTalk 接口,如果有则调用 object.GetReply("Hello")并且对象可以响应。因此,如果您愿意,您可以拥有会说话的门和石头。您将获得处理与事物交谈/显示响应等的所有代码,使用 ICanTalk 接口方法,然后其他类可以实现 ICanTalk 并且它们各自决定如何响应被交谈。这个概念被称为“关注点分离”,可以帮助您创建更多可重用的代码。
重要的是你可以编写一段代码、一个算法、函数等,只适用于那个接口,这样一旦你让那个代码和接口一起工作,你就可以在任何类上使用那个接口,并且该类可以利用现有代码。
即你的condition
函数,如果它接受了一个 IAbility 接口,一旦你的代码工作,那么你创建的任何实现 IAbility 的类都可以传递给条件函数。条件函数负责做它应该做的任何事情,实现 IAbility 的类负责它实现的方法中特定于它的任何事情。
当然,实现抽象类或接口的类必须实现所需的方法,所以有时您可能会觉得自己在复制代码。例如,如果您有类似的类,例如 TrappedDoor 和 Door,如果 TrappedDoor 未设置/已经弹出,则 TrappedDoor 的行为可能与常规 Door 一样。因此,在这种情况下,您可能要么继承自 Door,要么拥有私有 Door 属性(称为“组合”)。如果陷阱已经弹出,那么您可以调用基类 Door 或私有 Door 属性并调用 .Turn ,以便在陷阱未激活的情况下重用常规门的默认行为。
测试对象是否实现接口
就我个人而言,我主要使用接口和组合,而不是继承。并不是说继承很糟糕,而是继承层次结构很快就会变得非常复杂。