【问题标题】:Overloaded functions with inherited parameter具有继承参数的重载函数
【发布时间】:2020-03-04 07:33:42
【问题描述】:

我正在尝试做这样的事情,但我遇到错误

无法从 AbstractExampleClass 转换为 SpecificExampleClassA。

所以我可能在这段代码中走错了方向,谁能告诉我出了什么问题以及如何修复它。

public abstract class AbstractExampleClass 
{
    // Code goes here
}

public class SpecificExampleClassA : AbstractExampleClass 
{

}

public class SpecificExampleClass : AbstractExampleClass 
{

}

public class handler 
{
    public void Handle(AbstractExampleClass aec)
    {
        HandleSpecific(aec);
    }

    public void HandleSpecific(SpecificExampleClassA a)
    {
        // DoSomething
    }

    public void HandleSpecific(SpecificExampleClassB b)
    {
        // DoSomething Else
    }

}

【问题讨论】:

    标签: c# overloading abstract-class


    【解决方案1】:

    重载是在编译时解决的,所以你不能指望它根据aec运行时类型来决定调用哪个重载。 调用的重载必须在编译时决定。

    您真正需要的是“subtyping”类型的多态性(也就是 C# 术语中的“多态性”),而不是 ad hoc polymorphism(又名“重载”)。

    改为在子类中移动处理程序方法:

    public abstract class AbstractExampleClass 
    {
        public abstract void Specific();
    }
    
    public class SpecificExampleClassA : AbstractExampleClass 
    {
    
        public override void Specific()
        {
            // DoSomething
        }
    }
    
    public class SpecificExampleClass : AbstractExampleClass 
    {
    
        public override void Specific()
        {
            // DoSomething Else
        }
    }
    
    public class handler 
    {
        public void Handle(AbstractExampleClass aec)
        {
            aec.Specific();
        }
    }
    

    【讨论】:

      【解决方案2】:

      这可以由Visitor Pattern处理

      public abstract class AbstractExampleClass 
      {
          public abstract void Accept( Handler handler );
      }
      
      public class SpecificExampleClassA : AbstractExampleClass 
      {
          public override Accept( Handler handler )
          {
              handler.HandleSpecific( this );
          }
      }
      
      public class SpecificExampleClass : AbstractExampleClass 
      {
          public override Accept( Handler handler )
          {
              handler.HandleSpecific( this );
          }
      }
      
      public class Handler // the Visitor
      {
          public void Handle(AbstractExampleClass aec)
          {
              aec.Accept( this );
          }
      
          public void HandleSpecific(SpecificExampleClassA a) // visit method
          {
              // DoSomething
          }
      
          public void HandleSpecific(SpecificExampleClassB b) // visit method
          {
              // DoSomething Else
          }
      }
      

      【讨论】:

        【解决方案3】:

        如果你真的必须这样做,你可以这样做:

            public void Handle(AbstractExampleClass aec)
            {
                switch (aec)
                {
                    case SpecificExampleClassA a:
                        HandleSpecific(a);
                        break;
                    case SpecificExampleClassB b:
                        HandleSpecific(b);
                        break;
                    default:
                        throw new Exception($"What do I do with a '{aec?.GetType()}'?");
                }
            }
        

        但如果允许您这样做,我推荐一种类似于 Sweeper 回答中的方法。

        【讨论】:

          猜你喜欢
          • 2020-07-24
          • 1970-01-01
          • 2023-04-04
          • 1970-01-01
          • 1970-01-01
          • 2012-05-12
          • 1970-01-01
          • 1970-01-01
          • 2017-11-20
          相关资源
          最近更新 更多