C#,Unity - 采用多个不同对象的单一功能

时间:2013-01-10 22:29:58

标签: c# class function inheritance abstract

我需要你的帮助。 我正在安排一个脚本,可以在RPG游戏中执行异能之前检查各种条件。

所有这些能力都属于个别类别(火球,治疗,毒药),所有这些都来自另一个抽象类(远程能力,治疗能力,DOT能力),它们都是抽象类(能力)的父级。

为了避免创建多个功能,要处理每一项能力:

void condition(Fireball f){//test}; 
void condition(Heal f){//test}; 
void condition(Poison f){//test};

我正在尝试创建一个可以承担所有类型功能的单个函数调用。

void condition(Ability f){//test}

到目前为止,我已经成功创建了一个Fireball对象并将其传递给函数。

Fireball _fire = new FireBall();
condition(_fire);

void condition(Ability f){//test}

从这里我可以访问在Ability类中初始化的所有公共变量,但是我无法访问在派生类中初始化的公共变量(Ranged ability,Healing ability,DOT ability)。

是我遗忘了什么,还是我从错误的角度看待这个? (我不善于利用继承和抽象类。)

1 个答案:

答案 0 :(得分:8)

如果不了解条件函数的更多细节,您有两种选择。

一,你可以做点什么

if (f.GetType() == typeof(FireBall))
{
  fireBall = (FireBall)f;
  fireBall.FireTheFireBall();
}
else if (f.GetType() == typeof(Heal))
...

或者,您的能力可以有一个抽象的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
}

然后,任何与Ability一起工作的东西都可以调用someAbility.Activate(),并且派生类提供的实现将被执行。

您还应该研究接口,这有点像抽象类。接口的好处是可以实现多个接口,而您只能从一个基本抽象类继承。想想具有Turn和Pull功能的IKnob接口。您可能有一个实现IKnob的Drawer类,一个Door类,一个实现Turn并激活陷阱的TrappedDoor类。玩家走到门口,然后点击它上面的“使用”按钮,然后你将对象打开(IKnob旋钮)

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(“你好“)和对象可以响应。如果你愿意的话,你可以有说话的门和岩石。您将获得处理与事物/显示响应等的所有代码以及使用ICanTalk接口方法,然后其他类可以实现ICanTalk,并且每个类都决定它们如何响应以进行交谈。这个概念被称为“关注点分离”,可以帮助您创建更多可重用的代码。

重要的是你可以编写一段代码,一个算法,一个函数等,它只适用于那个接口,这样一旦你使用该接口的代码,你可以在任何接口上使用该接口class,该类可以利用现有的代码。

即。你的condition函数,如果它有一个IAbility接口,一旦你有了这个代码,那么你创建的任何实现IAbility的类都可以传递给condition函数。条件函数负责执行它应该做的任何事情,并且实现IAbility的类在它实现的方法中处理它所特定的任何内容。

当然,实现抽象类或接口的类必须实现所需的方法,因此有时您可能会觉得您正在复制代码。例如,如果您有类似的类,如TrappedDoor和Door,如果陷阱没有设置/已经弹出,则TrappedDoor可能会像常规门一样运行。因此,在这种情况下,您可能会从Door继承,或者拥有私有的Door属性(称为“组合”)。如果陷阱已经弹出,那么您可以调用基本Door类或私有Door属性并调用.Turn,以便在陷阱未激活的情况下重新使用常规门的默认行为。

Test if object implements interface

我个人主要使用接口和组合,而不是继承。这种继承并不可怕,但继承层次很快就会变得非常复杂。