C# 继承-调用子方法而不是父方法

C# 继承-调用子方法而不是父方法,c#,oop,inheritance,abstract-class,abstract,C#,Oop,Inheritance,Abstract Class,Abstract,这将很难解释为什么我要做的事情我要告诉你,但他们有一个原因,所以留在这里和我在一起。(欢迎提出建议) 我有一个函子,它在输入时调用一个方法 !请注意函子实际上是一个扩展方法,因此必须有类型推断 另外,我有一个带有2个child的抽象类和一个需要方法签名的接口 示例代码如下所示: public sealed class AbstractionTester { internal static void Run() { // The functor here accep

这将很难解释为什么我要做的事情我要告诉你,但他们有一个原因,所以留在这里和我在一起。(欢迎提出建议)

我有一个函子,它在输入时调用一个方法

!请注意函子实际上是一个扩展方法,因此必须有类型推断

另外,我有一个带有2个child的抽象类和一个需要方法签名的接口

示例代码如下所示:

public sealed class AbstractionTester
{
    internal static void Run()
    {
        // The functor here accepts A type but in my original code its just a generic type. 
        // I wanted to keep it simple for this example only 
        Func<A, bool> func = a =>
        {
            a.CallMe(); //Displays "Error"
            return true;
        };

        B obj = new B();
        func(obj);
    }
}

internal interface ICallMe<T> 
    where T : MyEntity
{
    T CallMe();
}

//Just a class which holds data I would like to store about every object I have, for example: CreateDate
internal abstract class MyEntity
{ }

internal abstract class A : MyEntity, ICallMe<A>
{
    //some other fields i would like to store..

    // This method here must never be invoked
    public A CallMe()
    {
        //throw new Exception();
        Console.WriteLine("Error");
        return this;
    }
}

internal class B : A, ICallMe<B>
{
    public new B CallMe()
    {
        Console.WriteLine("B");
        return this;
    }
}

internal class C : A, ICallMe<C>
{
    public new C CallMe()
    {
        Console.WriteLine("C");
        return this;
    }
}
公共密封类抽象测试仪
{
内部静态无效运行()
{
//这里的函子接受一个类型,但在我的原始代码中它只是一个泛型类型。
//我只想对这个例子保持简单
Func Func=a=>
{
a、 CallMe();//显示“错误”
返回true;
};
B obj=新的B();
func(obj);
}
}
内部接口ICallMe
T:MyEntity在哪里
{
T叫我();
}
//只是一个类,它保存我想要存储的关于我拥有的每个对象的数据,例如:CreateDate
内部抽象类MyEntity
{ }
内部抽象类A:MyEntity,ICallMe
{
//其他一些我想存储的字段。。
//这里的方法不能被调用
公共电话号码()
{
//抛出新异常();
控制台写入线(“错误”);
归还这个;
}
}
内部B类:A,ICallMe
{
公共新B CallMe()
{
控制台。写入线(“B”);
归还这个;
}
}
内部C类:A,ICallMe
{
公共新C CallMe()
{
控制台。写入线(“C”);
归还这个;
}
}
每次我调用Run()时,结果是错误会显示在屏幕上。 我可以做些什么来强制我拥有的这个函子不会在父类中执行该方法

函子无论如何都不会收到A的实例,因为A是抽象的(我指的是纯A,而不是A的子)

其他信息:

  • 我必须在类
    B
    C
    中明确写出
    CallMe
    的返回类型。我无法将它们更改为类型
    A
  • 我需要在函子中保留A(或类似的东西)的类型,因为我需要为某些代码延续推断类型

    • 这里有一个解决方案,它不需要将
      公共调用定义为
      虚拟
      。这样做的好处是,子类可以将其
      CallMe()
      定义为
      new
      ,以便返回
      B
      C
      。但它要求您可以将类
      设置为public
      ,而不是
      internal
      (否则您将获得)

      使用动态调度调用实际运行时类型,而不是在接口中声明的类型:

      Func<A, bool> func = a => {
           var runtimeType = (dynamic)a;
           runtimeType.CallMe(); 
           return true;
       };
      

      Func

      这有一个特定的语言特性;接口重新实现

      显式重新实现接口,并使泛型函子具有可调用的
      iCalable


      为什么需要将
      A
      保留在任何地方?

      确保A的
      CallMe
      方法从不被调用的最佳方法是使其不存在

      现在,它永远无法根据需要调用

      现在,使接口协变:

      internal interface ICallMe<out T> 
          where T : MyEntity
      {
          T CallMe();
      }
      
      内部接口ICallMe
      T:MyEntity在哪里
      {
      T叫我();
      }
      
      然后将
      Func
      更改为
      Func

      公共密封类抽象测试仪
      {
      内部静态无效运行()
      {
      //这里的函子接受一个类型,但在我的原始代码中它只是一个泛型类型。
      //我只想对这个例子保持简单
      Func Func=a=>
      {
      a、 CallMe();//显示“B”
      返回true;
      };
      B obj=新的B();
      func(obj);
      }
      }
      
      这真是一个奇怪的实现。为什么不使用访客模式

      然后你可以做:

          static void Main(string[] args)
          {
              Element a = new A();
              Element b = new B();
              Element c = new C();
              ICallMe callMe = new CallMe();
              a.accept(callMe);
              b.accept(callMe);
              c.accept(callMe);
          }
      
      实施情况如下:

      public interface ICallMe
      {
          void Visit(A a);
          void Visit(B b);
          void Visit(C c);
      }
      
      public class CallMe : ICallMe
      {
          public void Visit(A c)
          {
              Console.WriteLine("A");
          }
      
          public void Visit(B b)
          {
              Console.WriteLine("B");
          }
      
          public void Visit(C a)
          {
              Console.WriteLine("C");
          }
      }
      
      interface Element
      {
          void accept(ICallMe visitor);
      }
      
      public class A : Element
      {
          public void accept(ICallMe visitor)
          {
              visitor.Visit(this);
          }
      }
      public class B : Element
      {
          public void accept(ICallMe visitor)
          {
              visitor.Visit(this);
          }
      }
      public class C : Element
      {
          public void accept(ICallMe visitor)
          {
              visitor.Visit(this);
          }
      }
      

      为什么不在A的B类方法中
      重写
      ,而是使用
      新建
      ?@Tigran,因为方法CallMe是在接口中定义的。如何实现相同的通用接口两次?只有返回类型不同吗?@JeroenvanLangen我在哪里说过我两次执行泛型交互?如果您指的是functor参数类型,那么它将推断该类型,因为在我的代码中,functor实际上是一个扩展方法。如果你提到我写ICallMe的事实,这个例子就最小化了,在我的原始代码中,我几乎在我所有的类上都使用它。它在这里:
      内部抽象类A:MyEntity,ICallMe
      和这里
      内部类B:A,ICallMe
      所以:
      ICallMe
      ICallMe
      ,这就是问题所在。它们使用不同的返回类型强制实现2个方法。不能定义只在返回类型上不同的相同methodname。(重载问题)如果您从
      T CallMe()更改返回类型
      void CallMe(out T)
      它会起作用。除非绝对需要,否则我宁愿不使用铸造。对不起,我想到的唯一其他方法是使用
      虚拟
      ,它不符合您的要求:(我不想在functor的参数和iCalable之间设置约束。我需要确定其中的类型。如果您仔细阅读我的帖子,我提到functor实际上是一个扩展方法,所以我需要将类型a保留在那里。@OriRefael那么您如何考虑将其设置为泛型(正如您在问题中指出的那样)如果您不以某种方式约束泛型类型以便编译器知道调用是安全的,则调用
      CallMe()
      。@oriefeal您的扩展方法的签名是什么?如果您不发布相关代码,则很难给出答案。实际上,我在最后选择了动态调度,但我可能会将其更改为访问者模式(我在写动态调度时也想到了这一点)它似乎就是解决方案。
      internal abstract class MyEntity
      { }
      
      internal abstract class A : MyEntity
      { }
      
      internal interface ICallMe<out T> 
          where T : MyEntity
      {
          T CallMe();
      }
      
      public sealed class AbstractionTester
      {
          internal static void Run()
          {
              // The functor here accepts A type but in my original code its just a generic type. 
              // I wanted to keep it simple for this example only 
              Func<ICallMe<A>, bool> func = a =>
              {
                  a.CallMe(); //Displays "B"
                  return true;
              };
      
              B obj = new B();
              func(obj);
          }
      }
      
          static void Main(string[] args)
          {
              Element a = new A();
              Element b = new B();
              Element c = new C();
              ICallMe callMe = new CallMe();
              a.accept(callMe);
              b.accept(callMe);
              c.accept(callMe);
          }
      
      public interface ICallMe
      {
          void Visit(A a);
          void Visit(B b);
          void Visit(C c);
      }
      
      public class CallMe : ICallMe
      {
          public void Visit(A c)
          {
              Console.WriteLine("A");
          }
      
          public void Visit(B b)
          {
              Console.WriteLine("B");
          }
      
          public void Visit(C a)
          {
              Console.WriteLine("C");
          }
      }
      
      interface Element
      {
          void accept(ICallMe visitor);
      }
      
      public class A : Element
      {
          public void accept(ICallMe visitor)
          {
              visitor.Visit(this);
          }
      }
      public class B : Element
      {
          public void accept(ICallMe visitor)
          {
              visitor.Visit(this);
          }
      }
      public class C : Element
      {
          public void accept(ICallMe visitor)
          {
              visitor.Visit(this);
          }
      }