In a comment for a previous post (Top 10 differences between Java and C#), John P. Wood wrote:
As a (primarily) Java developer, I’ve also noticed that C# handles abstract classes that implement interfaces differently. In Java, an abstract class can implement an interface, and not provide implementations of all of the interface’s methods. It is the responsibility of the first concrete class that has that abstract class as an ancestor to implement all of the methods in the interface.
C# on the other hand seems to require that the abstract class provide implementations for all of the methods on the interface. Even if that implementation is just a method signature.
Like these 3 posts (1 (bottom), 2, 3), I am struggling with why the Microsoft Team chose to do this. Why ask the developer to write a little stub for the interface method, when the abstract class has no intention of implementing it at all?
I believe it’s a natural artifact of virtual and non-virtual methods in C# (gotcha #2). In Java, methods are virtual by default (as far as I’m aware, Java doesn’t support non-virtual methods). However, C# (being derived from C++) does support non-virtual methods. When an abstract class implements an interface in C#, you are given the chance to describe the interface methods as abstract, virtual or non-virtual. Here’s exactly what each options means:
- abstract – No attempt at an implementation is made in the abstract class. It’s up to the first concrete class to provide an implementation. As a side note, defining a method as abstract implicitly defines it as virtual. If this weren’t the case, you wouldn’t be able to override it in the child class which defeats the purpose of an abstract method.
- virtual – An attempt was made in the abstract class to implement this method, but the child class has the option of overriding it and providing its own implementation.
- non-virtual – Again, an attempt was made at an implementation in the abstract class. However, the child class cannot override this method. If a child class defines a method with the same name, the method will not be associated with the interface implemented in the abstract class. The method associated with the interface is the non-virtual method defined by the abstract class.
Java can do options 1 and 2, but it lacks option 3. Java could define the method as final to prevent it from being overriden, but this is slightly different than non-virtual. The final keyword is more along the lines of seal in C#. By allowing an option 3, C# provides finer control over how interfaces are inherited. If C# went the route of Java and permitted abstract classes to put off interface method definitions, these methods would need to be virtual by default. However, this would be inconsistent with C# methods being non-virtual by default.
In a nutshell, the C# developer is forced in the abstract class to decide exactly which of the three options to assign to the interface method. Anyway, that’s my best guess…