【问题标题】:C# - Implement abstract or interface method inside of another methodC# - 在另一个方法中实现抽象或接口方法
【发布时间】:2019-10-02 16:40:15
【问题描述】:

我正在尝试在基于 switch case 的另一个方法中实现抽象或接口方法。根据给定的索引,我想实现不同的方法。

代码

public interface choices    
{    
    void Effect ();    
}

public class Imple : choices    
{    
    public void Choose(int index)    
    {    
        if(index == 1)    
        {    
            void Effect()    
            {    
            // implementation here


            }    
            else if(index == 2)
            // etc.

        }    
    }
}

可以通过重写抽象方法来完成吗? 谢谢。

--- 编辑 ---

我明白上面提供的代码和解释不清楚,所以我会尽量解释得更好。

我正在创建一个 Unity 游戏,但是我遇到的问题与接口和 c# 方法实现有关,这就是我没有询问 Unity 论坛的原因。对于这个游戏,我有不同属性的武器(比如伤害和智力、占用的手等),它们都可以正常工作。

项目类(基类)

public class Item
{
    // stats and getters / setters
}

武器类

public class Weapon : Item
{
    public void Attack()
    {
        // attack enemies and reduce their health
        // I want the Effect method to activate when attacking, 
        // if the method has been implementd
    }
}

我希望能够在运行时创建能够执行效果的不同方法,例如在击中敌人时造成更多伤害。但是,我想根据与效果对应的索引在运行时实现这些方法。原因是武器存储在一个 json 文件中,在解析它时,该索引将有助于识别武器具有的效果。因此,如果 index 为 1,则实现应该允许武器造成额外伤害,但如果为 2,则会产生不同的效果。为此,我创建了一个 OnHit 类和一个 IOnHit 接口,如下所示:

public class OnHit : IOnHit
{
    public void Effect()
    {
        // empty
    }
}


public interface IOnHit
{
    void Effect();
}

我正在寻找一种方法来动态地实现这一点。我想到的一种方法是创建一个具有所有效果的静态类,然后将索引传递到那里并继续。但是,这对游戏来说是有问题的,因为每次玩家攻击时它都必须循环通过一个 switch case(如果玩家有 2 个武器,则为 2 个)。所以,我正在寻找一种方法来拥有一个接口或一个带有抽象方法的抽象类,这些抽象方法可以实现一次,然后在武器效果发生时调用。我的想法是在武器对象中创建一个 OnHit 类的实例,并在那里链接 IOnHit 接口。然后,像这样实现其中的代码:

public class Weapon : Item
{
    OnHit oh = new OnHit();
    IOnHit ioh = oh;
    public void Attack()
    {
        // previous attack method
        if(ioh.Effect is implemented)
            ioh.Effect();
    }

    public void SetIndex(int index)
    {
        switch{
            case 1:
                ioh.Effect()
                {
                    // implementation of the effect
                }
            break;

            case 2:
                ioh.Effect()
                {
                    // implementation of different effect
                }
            break;
        }
    }
}

其中index参数是效果的id,取自解析的json。

再次感谢您。

【问题讨论】:

  • 您的问题目前没有意义。接口实现是为要调用的类外部的代码。为什么你会在类中尝试使用接口的方法,更不用说以条件实现的方式这样做了?
  • 原来的问题很清楚。不幸的是,你无法以这种方式实现你想要的。您必须直接在类上实现该方法(而不是嵌套在另一个方法中)。然后,如果您将其存储在私有字段中,则可以在其中放置一个使用 Choose() 值的开关或 if/else。

标签: c# interface delegates abstract


【解决方案1】:

您想要做的是委派。

所以在类实现中,你会创建两个私有或受保护的方法来实现效果。

然后,当您调用 Choose 方法时,它也会将您创建的委托引用字段设置为指向所需的方法。

现在你的Effect 方法调用委托引用,如果不为空(已初始化)。

static void Test()
{
  var instance = new Imple();
  instance.Choose(2);
  instance.Effect();
}

public interface choices
{
  void Effect();
}

public class Imple : choices
{
  private Action SelectedEffect;

  public void Effect()
  {
    if ( SelectedEffect != null ) SelectedEffect();
  }

  private void Effect1()
  {
    Console.WriteLine("Effect1 called.");
  }

  private void Effect2()
  {
    Console.WriteLine("Effect2 called.");
  }

  public void Choose(int index)
  {
    switch ( index )
    {
      case 1:
        SelectedEffect = Effect1;
        break;
      case 2:
        SelectedEffect = Effect2;
        break;
      default:
        throw new NotImplementedException("Effect version n°" + index);
    }
  }

}

Effect 可以指向任何类的任何方法:

  case 1:
    SelectedEffect = SomeReference1.SomeMethod;
    break;
  case 2:
    SelectedEffect = SomeReference2.SomeMethod;
    break;

您可以将Action 替换为任何方法签名以匹配参数和任何返回类型。

【讨论】:

    【解决方案2】:

    如果您要根据传递给Choose 的参数更改Effect 的实现行为,那么您将不得不使用状态字段来存储它并在Effect 中读取它,像这样

    public class Imple : choices    
    {    
        private int effectNum = 1; // set the default effect here
    
        public void Choose(int index)    
        {    
            effectNum = index;   
        }
    
        public void Effect()
        {
            switch (effectNum)
            {
                case 1: // implement the different effects here
                    break;
                case 2:
                    break;
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-05-08
      • 2014-06-30
      • 1970-01-01
      • 2020-02-04
      • 2011-11-20
      • 1970-01-01
      • 2021-11-01
      相关资源
      最近更新 更多