4

It seems to me like the C# 8.0 feature, default interface member implementation, essentially allows one to create implementations at the interface level. Pairing that with the fact that a class can implement multiple interfaces, it seems eerily close to a multiple inheritance structure for classes. As far as I understand, this seems to be quite opposite to the core of the design of the language.

Where does this discrepancy stem from and what room does this leave for actual abstract classes to occupy?

This question has been suggested as an answer to mine and while it is useful, it doesn't exactly answer my question. To be more precise:

  • I always assumed that single inheritance is one of the core principles of C#'s design, which is why the decision to implement this feature is surprising to me, and I would be interested to know where it stems from (C#-specifically).
  • The linked question does not answer what room it leaves for abstract classes.
user622505
  • 743
  • 6
  • 23
  • @Aomine while that question does contain useful insights, it only answers my first question tangentially (i.e. not C#-specific, with regards to the language's design which I always believed single inheritance was a major principle of) and doesn't answer my second question at all – user622505 Nov 29 '18 at 00:22
  • Well, C# has always allowed multiple interfaces to be implemented. The default implementations require the object to be cast as the interface with implementation, similar to how explicit interface implementations currently work. I'm not certain that default methods change the model very much. – Jonathon Chase Nov 29 '18 at 00:26
  • @JonathonChase multiple interface implementation is not the same thing as inheriting multiple implementations, though. I'm by no means saying it's a wrong design decision. I see it opening up room for abuse, but the good use cases might very well far outweigh the risks. I haven't worked with a language supporting this feature before, though, so I'm curious about the impact - hence the question. – user622505 Nov 29 '18 at 00:30
  • I believe that interface implementations are equivalent to copying the interface implementation into the class as an explicit interface implementation; unless the implementing class already has an implementation in which case it is dropped. Basically like a default implementation. This is not the same as having multiple base classes laid out within the class. – sjb-sjb Nov 29 '18 at 00:48
  • Yes, there is multiple inheritance to some extent. As said in the link you've posted "The main drive for default methods is interface evolution which means being able to add methods to an interface in future versions without breaking source or binary compatibility with existing implementations of that interface." if this is not what you're after then what type of answer are you after when you say "and I would be interested to know where it stems from (C#-specifically)." ? .Further, default methods in interfaces certainly does not replace abstract classes. – Ousmane D. Nov 29 '18 at 00:56
  • sjb-sjb / TheGeneral okay, that makes sense if it's structurally different than a base class. Would you mind posting that as an answer, ideally with a source? – user622505 Nov 29 '18 at 01:15
  • @Aomine "default methods in interfaces certainly does not replace abstract classes" is just an assertion that the linked answer does not answer. It would be useful then to answer why they don't replace abstract classes - is it just convention, or is there an actual structural difference? The other comments suggest that there is an actual difference, which would explain that they're not interchangeable, which definitely constitutes a solid foundation for an answer to my second question. I can concede that your linked answer actually does mostly answer my first question, though. – user622505 Nov 29 '18 at 01:16
  • @Lasooch " It would be useful then to answer why they don't replace abstract classes" --> An interface cannot define class level variables/fields (which I've touched on in the linked answer but maybe not enough so I can understand why you feel it doesn't answer your second question.) – Ousmane D. Nov 29 '18 at 01:24
  • 2
    @Lasooch default interface methods are used to implement *traits*. That's how they are [used in Java](https://opencredo.com/blogs/traits-java-8-default-methods/) since Java 8. PHP has traits [since 5.4](http://php.net/manual/en/language.oop5.traits.php). They can *replace* abstract classes in a few cases but that's not the main use case. The main benefit is composition of traits without multiple inheritance – Panagiotis Kanavos Nov 29 '18 at 15:39
  • 1
    @Lasooch [check this answer](https://stackoverflow.com/a/53450332/134204) to a question related to traits in C#. The code is specific to that question so not exactly suitable as an answer here without modifications. It contains a couple of links to Sharplab.Io examples though that show how the compiler treats traits/default interface methods – Panagiotis Kanavos Nov 29 '18 at 15:43
  • Thank you all for your answers and comments, very helpful! – user622505 Nov 29 '18 at 22:09

3 Answers3

6

I always assumed that single inheritance is one of the core principles of C#'s design

This is just not accurate. Single inheritance is a means to design goal, but not a goal in itself.

It's like saying the automatic transmission is a core design principle for car makers, when the actual goal is making the car easier and safer. And looking the car market, manual transmissions still thrive in both the low end (because they're cheaper) and the high end (performance sports cars) of the market, where they are good fit for purpose. Many models in those areas can still be had with either type of transmission.

The actual design goal in C# leading to single inheritance is more about safety and correctness with regards to memory access and overload resolution. Multiple inheritance is difficult to verify mathematically for these things compared to single inheritance. But as they find elegant solutions, C# designers have added a number of features that stretch the bounds of single inheritance. Beyond interfaces, we have partial classes, generics (and later co/contravariance), and delegate members that all trend this direction.

In this case, the default implementation is effective in safely providing a weak multiple inheritance because the inherited functionality doesn't cascade down the inheritance tree from two directions. You can't create a conflict by inheriting two different classes with differing interface implementations; you are limited to either your own class implementation, the default implementation, or the single implementation available via inheritance.

Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
2

Note that default interface implementation does not allow for multiple inheritance, at least not in the sense that was a problem for C++. The reason multiple inheritance is a problem in C++ is that when a class inherits from multiple classes that have methods with equal signatures, it can become ambiguous as to which implementation is desired. With default interface implementation, that ambiguity is impossible because the class itself does not implement the method. An object must be cast to the interface in order to call the implemented methods. So multiple methods with the same signature may be called on the same instance, but you must explicitly tell the compiler which method you are executing.

D Stanley
  • 149,601
  • 11
  • 178
  • 240
1

The linked post answers your first question to a good extent.

As for:

The linked question does not answer what room it leaves for abstract classes.

While it may read and sound similar interface default method implementation certainly does not replace abstract classes nor does it make them redundant, the very big reason being:

an interface cannot define class level fields/variables whereas an abstract class can have state.

There are some other differences although not as big as the aforementioned, which you can find in various blogs/posts:

etc.

Ousmane D.
  • 54,915
  • 8
  • 91
  • 126