How can you call an explicitly declared member of an interface in a base class from a subclass?

Say you have access to the MyClass base class, which implements "IFoo". "IFoo" defines the function "int FooValue ()", and "MyClass" implements it explicitly. Now say that you have a subclass of “MyClass” called “MySubClass” and you want to override FooValue in that subclass, but also want the implementation of the subclass to be based on the result of the base class implementation.

Now, as a rule, this can be solved by simply translating the implementation into a protected function in the base class, which we simply pass into a subclass. Done and done. But we do not have access to the source code of the base class. We only have a link to the library. So how do you solve this?

Do not duplicate (update: ... like this one)!

Here is this SO question here ... C #: redefining properties by explicitly specifying an interface ... which shows that you cannot redefine the base class interface through regular channels as such, you can explicitly reimplement the same interface in subclass and which behaves as if you are redefining the interface (but in fact you are reimplementing it, not redefining it). This suggests that I am trying to figure out how I can get the base class implementation. (This is why IMHO is not a duplicate of this question.)

Here is some pseudo-code of the base class, which again, we do not have access to the code ...

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

This is what we are trying to do, but obviously it is not allowed because you cannot use a “base” like this.

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

So is this possible?

+6
source share
2 answers

I will be honest, there is no direct answer to this. Sounds like a language restriction. Maybe there is a good reason for his absence.

However, I can think of some not-so-clean jobs around.

  • Reflection. Imho, the easiest option here. One of those rare cases where reflection is really necessary.

  • Its own interface and base class derived from the reference library.

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

    And you are dealing with IRealFoo , MyRealClass , etc. instead of IFoo , MyClass , etc.

     IRealFoo x = new MyRealClass(); IRealFoo y = new MyRealSubClass(); Console.WriteLine(x.FooValue()); //4 Console.WriteLine(y.FooValue()); //8 
  • Same as above, but an abstract class instead of an interface.

    Same as above, but you can also have an abstract base class RealFoo instead of the IFoo interface. This, I think, is a bit simpler, but not necessarily good code. It completely changes the purpose of the code.

     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 
  • Extension method along with dynamic.

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

    In this case, you can stick with the familiar IFoo interface, but you need to call the extension method RealFooValue instead of FooValue . When calling FooValue this will be confused with a potentially incorrect result. I do not recommend.

     IFoo x = new MyRealClass(); IFoo y = new MyRealSubClass(); Console.WriteLine(x.RealFooValue()); //4 Console.WriteLine(y.RealFooValue()); //8 
  • The inclusion type with if-else logic .

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

    This has the same problem as above. Not recommended.

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

An explicit interface implementation means that IFoo.FooValue () is private (you can check it with reflection):

  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.... } 

therefore you cannot call inherited IFoo.FooValue ().

Possible way

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

See also non-virtual interface template.

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

0
source

Source: https://habr.com/ru/post/950225/


All Articles