Why is it possible to implement an interface method in a base class?

In my project, I found a strange situation that seems completely valid in C #, because I don't have compile-time errors.

A simplified example is as follows:

using System; using System.Collections.Generic; namespace Test { interface IFoo { void FooMethod(); } class A { public void FooMethod() { Console.WriteLine("implementation"); } } class B : A, IFoo { } class Program { static void Main(string[] args) { IFoo foo = new B(); foo.FooMethod(); } } } 

Such code is compiled. However, note that A not IFoo , and B does not implement IFoo methods. In my case, by chance (after refactoring), A has a method with the same signature. But why does A know how to implement the FooMethod interface? A does not even know that IFoo exists.

For me, this design is dangerous. Since every time I implement some interface, I have to check if each method in this interface does not interfere with the methods of the base class.

If it is a "pure C # function"? How it's called? Did I miss something?

+57
c # interface
Feb 05 '13 at 9:16
source share
10 answers

For each member in the interface, the compiler simply looks for an explicit implementation (if any), and then a public implementation (implicit implementation), that is, a public API method that matches the interface signature. In this case, A.FooMethod() looks like a good match for public implementation. If B was unsatisfied with this choice, he could either use the method new , or use an explicit implementation; the latter would prefer:

 void IFoo.FooMethod() { /* explicit implementation */ } 
+37
Feb 05 '13 at 9:20
source share

The keyword here is implements . Your base class, although it knows nothing about IFoo , has declared a method signature that implements a method in your interface somewhere in your class hierarchy.

Therefore, when you implement IFoo in a derived class, it already has a method signature implemented inside the class structure, so therefore it does not need to be repeated.

If you have this:

 interface IFoo { void FooMethod(); } class A { private void FooMethod(){} } class B : A, IFoo { } 

You need to implement IFoo in this case, because the IFoo structure IFoo not available in the place where it is implemented, and as Mark says. You can implicitly implement an interface by executing IFoo.FooMethod() to make sure you have an implementation, despite having the appropriate method signature already defined in the hierarchy.

+18
Feb 05 '13 at 9:19
source share

You say in the comment

How likely is it that someone who wrote an implementation of the FooMethod in A class that does not implement IFoo actually means implementing IFoo ?

Well, it doesn't matter what author A thought when creating A This is the author of B , who must take responsibility for the fact that B inherits from A and implements IFoo . Author B needs to think about the implications of Definition B

You also say

In my case, accidentally (after refactoring) A has a method with the same signature

suggesting that this situation arose after A and B were written. In this case, the situation changes: when editing a class that is * inherited from * (for example, A ), the editor's responsibility is to check the editing effects in all inheritance classes .

+11
Feb 05 '13 at
source share

To implement an interface, a class must only (a) state that it implements this interface (for example, your class B), and (b) provides an implementation for all methods defined in the interface, either directly or indirectly through the base class (for example, your class B).

+2
Feb 05 '13 at 9:20
source share

This function is called inheritance. And if you don't like the design, just don't use it. Many people don't like inheritance, so you can. The definition of inheritance is that all members of the base class are also members of the derived. Thus, there are no compiler errors. Therefore, Derived implements the IFoo contract. This is an element of the base class that fulfills this requirement.

The beauty is that you can implement the interface through basic functionality (virtual), which can be overridden if Derived is expected to behave differently.

+1
Feb 05 '13 at 9:22
source share

Interfaces are not inherited, interfaces are implemented. So when you get the class from the interface, it means

In this interface you will find a method that implements the method that you provided.

Since the base class has a method implementation, there will be no problems with the same method signature defined in the interface.

Even if you write a second interface with the same method enabled, it will still work.

 interface IFoo2 { void FooMethod(); } class B : A, IFoo, IFoo2 { } 
+1
Feb 05 '13 at 9:23
source share

Section 13.4.4. C # specifications:

The mapping of an interface for a class or structure C finds an implementation for each member of each interface specified in the list of base class C. The implementation of a specific member of the IM interface, where I am the interface in which the member M is declared, is determined by examining each class or structure S , starting with C and repeating for each subsequent base class C until a match is found:

So, it seems that this is a well-defined behavior, since the correct implementation of FooMethod not found in B , so the search is performed in the base class A , where a method with a matching signature is found, This is even explicitly stated in the same section of the specification:

Members of the base class are involved in the display of the interface. In the example

 interface Interface1 { void F(); } class Class1 { public void F() {} public void G() {} } class Class2: Class1, Interface1 { new public void G() {} } 

Method F in Class1 is used in the implementation of Class2 Interface1.

+1
Feb 05 '13 at 12:26
source share

B execute IFOO . B inherits from A , so it looks something like this:

 class B : IFoo //Notice there is no A here. { public void FooMethod() { Console.WriteLine("implementation"); } } 

And it’s clear (from the code above) that B implements IFOO , and nothing special.

0
Feb 05
source share

While it’s not particularly useful to ponder why the C # creators did what they did, and although I don’t like this feature, I suspect that part of the reason it works, as it happens, is to that there is no other good syntax to indicate that an interface should be implemented by an existing base class method. The requirement that the derived class define methods that do nothing but chain to the implementation of the base class would seem ugly.

It has been said that it would be easier if C # resolved this common problem (interface methods that are related to other members are ugly) by providing syntax for explicitly attaching an interface member to a class member than using autoconnecting semantics to handle one specific situation. but requires a chain in a more common situation (implementing an interface using a protected virtual method):

secure virtual IFoo_Method (int a, int b, int c) {...}

IFoo.Method (int a, int b, int c) {IFoo_Method (a, b, c); }

While JITTER can understand that the call to IFoo_Method needs to be enabled, it really is not necessary. It would seem cleaner to declare that the protected method IFoo_Method should be considered as an implementation of IFoo.Method .

0
Feb 05 '13 at 21:28
source share

"But why should A know how to implement the FooMethod of the IFoo interface? Doesn't even know that IFoo exists.

A does not need to know about the existence of the IFoo interface. It is not Responsibility for the correct implementation of FooMethod. Apparently, A implemented a method that has the same signature as the IFoo FooMethod interface method.

Its responsibility B is to implement FooMethod, as it implements the IFoo interface. But since B already has a FooMethod method (inherited from A), it does not need to explicitly implement it. If the inherited method does not do its job, B can introduce a new method and write its own implementation.

0
Feb 06 '13 at 3:48
source share



All Articles