C#,Unity-取多个不同对象的单个函数

C#,Unity-取多个不同对象的单个函数,c#,class,function,inheritance,abstract,C#,Class,Function,Inheritance,Abstract,我需要你的帮助。 我正在安排一个脚本,可以在一个RPG游戏中执行一个能力之前检查各种条件。 所有这些技能都在单独的类(火球、治疗、毒药)中,所有这些技能都是从另一个抽象类(远程技能、治疗技能、点技能)派生出来的,它们都是抽象类(能力)的子类 为了避免创建多个功能,处理每个功能: void condition(Fireball f){//test}; void condition(Heal f){//test}; void condition(Poison f){//test}; 我正在尝试

我需要你的帮助。 我正在安排一个脚本,可以在一个RPG游戏中执行一个能力之前检查各种条件。 所有这些技能都在单独的类(火球、治疗、毒药)中,所有这些技能都是从另一个抽象类(远程技能、治疗技能、点技能)派生出来的,它们都是抽象类(能力)的子类

为了避免创建多个功能,处理每个功能:

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}
从这里我可以访问在能力类中初始化的所有公共变量,但是我不能访问在派生类中初始化的公共变量(范围能力、治疗能力、点能力)


是我忘记了什么,还是我从错误的角度看待这件事?(我不擅长利用继承和抽象类。)

如果不知道条件函数的更多细节,您有两个选择

第一,你可以做一些像

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
}
然后,任何与某个能力一起工作的东西都可以调用someAbility.Activate(),派生类提供的实现将被执行

您还应该研究接口,它有点像抽象类。接口的好处是您可以实现多个接口,而您仅限于从一个基本抽象类继承。考虑一个具有转向和拉动功能的IKnob接口。您可能有一个实现IKnob的抽屉类、一个门类、一个实现Turn并激活陷阱的TrappedDoor类。一个玩家走到一扇门前,点击门上的“使用”按钮,然后将对象“打开”(IKnob旋钮)传递到“打开”功能

有很多方法可以检查某个对象是否有接口,因此,如果某个玩家走到某个项目前试图与该项目对话,您可以检查该对象是否有ICanTalk接口,如果有,则调用object.GetReply(“Hello”),该对象可以响应。所以,如果你愿意,你可以有会说话的门和石头。您可以使用ICanTalk接口方法获得所有处理对话/显示响应等的代码,然后其他类可以实现ICanTalk,它们各自决定如何响应对话。这个概念被称为“关注点分离”,帮助您创建更多可重用的代码

重要的是,您可以编写一段代码、一个算法、函数等,这些代码只能与该接口一起工作,这样,一旦您使该代码与该接口一起工作,您就可以在任何类上使用该接口,该类可以利用先前存在的代码

也就是说,如果您的
条件
函数包含一个可维护性接口,那么一旦代码正常工作,那么您创建的实现可维护性的任何类都可以传递给条件函数。条件函数负责执行它应该执行的任何操作,而实现可重用性的类负责它所实现的方法中特定于它的任何操作

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


就我个人而言,我主要使用接口和组合,而不是继承。并不是说继承很糟糕,而是继承层次结构很快就会变得非常复杂。

经典的OOP多态性/继承问题:)要想找到一个既能保留封装又能舒适使用的解决方案是很困难也很有趣的+1.这与目标C有什么关系?对不起,我想我把它标错了。谢谢你的回答。我不确定第二个建议是如何起作用的,但我实际上认为第一个建议可能会起作用。我会尽快调查,我会报告:)@Marc更新以扩展第二个示例。第二个示例看起来更合理,我怀疑…:)是的,1)你不会得到一堆硬编码的开关箱。2) 每个特定的类都对其“特殊”行为负责。还添加了一些关于接口的注释。非常感谢AaronLS的回复。这确实是一个很好的方法,尽管我实际上有点害怕在我们当前的项目中使用它,因为我正在重新编程一个付费专业人员开发的许多课程。首先,我将利用父类等中的抽象方法,如果一切顺利,我可能会更深入地研究如何利用接口。
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");
    }
  }
}