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

时间:2017-03-01 14:42:10

标签: c# oop inheritance abstract-class abstract

我很难解释为什么我要做的事情即将告诉你,但他们有理由这样留在我身边。 (建议欢迎)。

我有一个Functor,它在输入时调用一个方法。

!请注意!仿函数实际上是一种扩展方法,因此必须进行打字推断。

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

示例代码如下所示:

result.next()

每当我调用Run()时,结果就是错误被推向屏幕。 我可以做些什么来强制执行我在父类中执行该方法的函子。

Functor永远不会收到A的实例,因为A是抽象的(我的意思是纯A,不是A的孩子)

其他信息:

  • 我必须明确地在课程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; } } CallMe中写下B的返回类型。我无法将其更改为C
  • 我需要在仿函数中保留A(或类似的东西)的类型,因为我需要推断某些代码延续的类型。

4 个答案:

答案 0 :(得分:1)

这实际上很奇怪。为什么不使用访客模式

然后你可以这样做:

    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);
    }
}

答案 1 :(得分:0)

这是一个无法将public A CallMe()定义为virtual的解决方案。这样做的好处是,子类可以将CallMe()定义为new,以便他们可以返回BC。但是,它要求您可以创建课程public而不是internal(或者您将获得an error)。

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

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

.net Fiddle

答案 2 :(得分:0)

这有一个特定的语言功能;界面重新实现。

明确重新实现界面并使通用仿函数采用ICallable<T>

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

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

你的算子应该是:

Func<T, bool> func = a => ... 

并且T应该被约束(在方法或类级别)ICallable<T>

更新:如果仿函数确实是扩展码,我不确定问题是什么:

 public static bool MyEnxtensionMethod<T>(T argument)
     where T: ICallable<T>
 {
      argument.CallMe();
      return true;
 }

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

答案 3 :(得分:0)

确保永远不会调用A CallMe方法的最佳方法是不存在。

internal abstract class MyEntity
{ }

internal abstract class A : MyEntity
{ }

现在永远不能按要求调用它。

现在使界面协变:

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

然后将Func<A, bool>更改为Func<ICallMe<A>, bool>

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);
    }
}