如何从子类中调用基类中显式声明的接口成员?

时间:2013-07-25 05:30:33

标签: c# interface override base

假设您可以访问实现“IFoo”的基类“MyClass”。 'IFoo'定义函数'int FooValue()','MyClass'显式实现它。现在假设您有一个名为'MySubClass'的'MyClass'的子类,并且您希望覆盖该子类中的'FooValue',但您还希望子类的实现基于基类实现的结果。

现在通常,这可以通过简单地将实现移动到基类中的受保护函数来解决,我们在子类中将其简单地覆盖。做完了。但是我们无法访问基类的源代码。我们只将其作为库的参考。那你怎么解决这个问题呢?

不重复(更新:......就像这一样)!

这里有这个问题...... C#: Property overriding by specifying the interface explicitly ...当你无法通过正常渠道本身覆盖基类的界面时,你可以显式重新在子类上实现相同的接口,其行为类似于覆盖接口(但实际上你正在重新实现它,而不是覆盖它。)那就是说,我想弄清楚的是我如何获得在基类的实现。 (这就是为什么恕我直言,这不是那个问题的重复。)

这是基类的一些伪代码,我们再也无法访问代码......

public interface IFoo
{
    int FooValue();
}

public class MyClass : IFoo
{
    int IFoo.FooValue() <-- Explicit implementation requiring a cast to access.
    {
        return 4;
    }
}

这是我们要做的,但显然不允许这样做,因为你不能像这样使用'base'。

public class MySubClass : MyClass
{
    int IFoo.FooValue()
    {
        int baseResult = ((IFoo)base).FooValue(); <-- Can't use 'base' like this
        return baseResult * 2;
    }
}

这可能吗?

2 个答案:

答案 0 :(得分:3)

我会诚实地说,没有直截了当的答案。感觉像是语言的限制。可能有一些合理的原因缺乏它。

但是,我可以想到一些不那么干净的工作。

  1. 反思。 Imho,这里最简单的选择。真正需要反思的极少数情况之一。

  2. 您自己的接口和基类派生自引用的库。

    //your interface
    public interface IRealFoo : IFoo
    {
        new int FooValue();
    }
    
    //your base class
    public class MyRealClass : MyClass, IRealFoo
    {
        protected virtual int FooValue()
        {
            return ((IFoo)this).FooValue();
        }
    
        int IRealFoo.FooValue()
        {
            return FooValue();
        }
    }
    
    //your child class
    public class MyRealSubClass : MyRealClass
    {
        protected override int FooValue()
        {
            return base.FooValue() * 2;
        }
    }
    

    您处理的是IRealFooMyRealClass,而不是IFooMyClass等。

    IRealFoo x = new MyRealClass();
    IRealFoo y = new MyRealSubClass();
    Console.WriteLine(x.FooValue()); //4
    Console.WriteLine(y.FooValue()); //8
    
  3. 与上述相同,但抽象类而非接口。

    与上面相同,但您也可以使用抽象基类RealFoo而不是接口IFoo。我认为这是一个稍微简单的代码,但不一定是好的代码。它彻底改变了代码的意图。

    public abstract class RealFoo : MyClass
    {
        public virtual int FooValue()
        {
            return ((IFoo)this).FooValue();
        }
    }
    
    public class MyRealClass : RealFoo 
    {
        public override int FooValue() 
        {
            return base.FooValue();
        }
    }
    
    public class MyRealSubClass : MyRealClass 
    {
        public override int FooValue() 
        {
            return base.FooValue() * 2;
        }
    }
    
    //call it like:
    RealFoo x = new MyRealClass();
    RealFoo y = new MyRealSubClass();
    Console.WriteLine(x.FooValue()); //4
    Console.WriteLine(y.FooValue()); //8
    
  4. 扩展方法以及动态

    public class MyRealClass : MyClass 
    {
        public virtual int FooValue() 
        {
            return ((IFoo)this).FooValue();
        }
    }
    
    public class MyRealSubClass : MyRealClass 
    {
        public override int FooValue() 
        {
            return base.FooValue() * 2;
        }
    }
    
    public static int RealFooValue(this IFoo foo) 
    {
        return ((dynamic)foo).FooValue();
    }
    

    在这种情况下,您可以使用熟悉的IFoo界面,但您必须调用扩展方法RealFooValue而不是FooValue。调用FooValue时,这可能会导致错误的结果。我不建议。

    IFoo x = new MyRealClass();
    IFoo y = new MyRealSubClass();
    Console.WriteLine(x.RealFooValue()); //4
    Console.WriteLine(y.RealFooValue()); //8
    
  5. 使用if-else逻辑启用类型。

    public class MySubClass : MyClass
    {
    
    }
    
    public static int RealFooValue(this IFoo foo) 
    {
        var type = foo.GetType();
    
        if (type == typeof(MyClass))
            return foo.FooValue();
        else if (type == typeof(MySubClass))
            return foo.FooValue() * 2; //logic goes here
    
        throw new Exception();
    }
    

    这与上述问题相同。不推荐它。

    IFoo x = new MyClass();
    IFoo y = new MySubClass();
    Console.WriteLine(x.RealFooValue()); //4
    Console.WriteLine(y.RealFooValue()); //8
    

答案 1 :(得分:0)

显式接口实现意味着IFoo.FooValue()是私有 (你可以通过反思来检查):

  MethodInfo mi = typeof(MyClass).GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).Where(m => m.Name.EndsWith("IFoo.FooValue")).ToList()[0];

  if (mi.IsPrivate) {
    // And it is private.... 
  } 

所以你不能打电话给 继承了IFoo.FooValue()。

可能的道路

  public interface IFoo
  {
      int FooValue();
  }

  public class MyClass : IFoo
  {
      // This (main logic) should be inherited/override 
      protected virtual int CoreFooValue() 
      {
          return 4;
      }

      // Just a non-virtual interface method which is immutable
      int IFoo.FooValue() 
      {
          return CoreFooValue();
      }
  }

  public class MySubClass : MyClass {
      // Logic is changed, interface is not 
      protected override int CoreFooValue() 
      {
          return base.CoreFooValue() * 2;
      }
  }

另请参阅非虚拟接口模式

http://en.wikipedia.org/wiki/Non-virtual_interface_pattern