What is the advantage of inheritance of interface?
Copy and Paste were the primary mechanisms of code reuse. Procedures and functions were rare, newfangled gadgets viewed with suspicion. Calling a procedure was expensive! Separating pieces of code from the main logic caused confusion! Show
It was a Dark Time. Then the light of object-oriented programming (OOP) shone upon the world… And the world pretty much ignored it for a few decades1. Until graphical user interfaces2, which turned out to really, really need OOP. When you click on a button in a window, what simpler way to generate appropriate responses than to send that button (or its surrogate) a Click message3? After that, OOP took off. Numerous4 books have been written and countless5 articles have proliferated. So by now, everyone understands object-oriented programming in detail, right? Sadly, the code (and the Internet) says no. The biggest point of confusion and contention seems to be composition versus inheritance, often summarized in the mantra “favor composition over inheritance”. Let’s talk about that. Mantras Considered HarmfulAs a heuristic, ‘favor composition over inheritance’ is okay, however, I am not a fan of mantras. While they often contain a kernel of truth, it is far too easy for people to hear the slogan without understanding its source or context, and thus avoid thinking for themselves - and that never turns out well.I am also not a fan of ridiculous clickbait headlines like “Inheritance is Evil”6, especially when the author attempts to back up such an outrageous claim by using inheritance inappropriately… and then blaming inheritance. Like a carpenter declaring that hammers are useless because they don’t drive screws well. Let’s start with the basics. DefinitionsHere is the definition of object-oriented programming that I will be using for the rest of the article: assume we have a ‘classic’ OOP language, i.e., one that supports classes with fields, methods, and single inheritance. No interfaces, no mixins, no aspects, no multiple inheritance, no delegates, no closures, no lambdas, nothing but the basics:
Inheritance is FundamentalInheritance is fundamental to object-oriented programming. A programming language may have objects and messages, but without inheritance it is not object-oriented (merely “object-based”, but still polymorphic).…and so is CompositionComposition is also fundamental to every language. Even if the language does not support composition (rare these days!), humans still think in terms of parts and components. It would be impossible to break down complex problems into modular solutions without composition.(Encapsulation is fundamental too, but we’re not going to talk about it much here.) So What’s the Fuss About?Composition and inheritance are both fundamental, so what’s the big deal?The big deal is in thinking that one can replace the other, in all cases, or that one is better or worse than the other. Like everything else in software development, there are trade-offs to be made. Composition is fairly easy to understand - we can see composition in everyday life: a chair has legs, a wall is composed of bricks and mortar, and so on. While the definition of inheritance is simple, it can become a complicated, tangled thing when used unwisely. Inheritance is more of an abstraction that we can only talk about, not touch directly. Though it is possible to mimic inheritance using composition in many situations, it is often unwieldy to do so. The purpose of composition is obvious: make wholes out of parts. The purpose of inheritance is a bit more complex because inheritance serves two purposes, semantics and mechanics. Inheritance SemanticsInheritance captures semantics (meaning) in a classification hierarchy (a taxonomy), arranging concepts from generalized to specialized, grouping related concepts in subtrees, and so on. The semantics of a class are mostly captured in its interface, the set of messages to which it responds, but a portion of the semantics also resides in the set of messages that the class sends. When inheriting from a class, you are implicitly accepting responsibility for all of the messages that the superclass sends on your behalf, not just the messages that it can receive. This makes the subclass more tightly coupled to its superclass than it would be if it merely used an instance of the superclass as a component instead of inheriting from it. Note that even in classes that don’t “do” much, the name of the class imparts significant semantic information about the domain to the developer.Inheritance MechanicsInheritance captures mechanics by encoding the representation of the data (fields) and behavior (methods) of a class and making it available for reuse and augmentation in subclasses. Mechanically, the subclass will inherit the implementation of the superclass and thus also its interface.The dual purpose of inheritance7 in most current OOP languages is, I believe, the cause of most confusion. Many people think that “code reuse” is the primary purpose of inheritance, but that is not its only purpose. An overemphasis on reuse can lead to tragically flawed designs. Let’s look at a couple of examples. How to Misuse Inheritance - Example 1Let’s start with a simple and extremely common example of misusing inheritance:class Stack extends ArrayList { public void push(Object value) { … } public Object pop() { … } } This class will function as a Stack, but its interface is fatally bloated. The public interface of this class is not just push and pop, as one would expect from a class named Stack, it also includes get, set, add, remove, clear, and a bunch of other messages inherited from ArrayList that are inappropriate for a Stack. You could override all of the unwanted methods, and perhaps adapt some useful ones (like clear), but that’s a lot of work to cover up a modeling mistake. Three modeling mistakes, actually, one semantic, one mechanical, one both:
How to Misuse Inheritance - Example 2Creating a domain-concept class by inheriting from an implementation class is a common misuse of inheritance. For example, suppose we want to do something with a certain segment of our customers. The easy and obvious thing to do is to subclass ArrayList, call it CustomerGroup, and start coding, right?Wrong. That would be a cross-domain inheritance relationship, and those should be avoided:
Single Inheritance is not the ProblemSingle inheritance is still the most common OOP model; single inheritance is necessarily implementation inheritance, which can lead to strong coupling between classes. The problem would seem to be that we have only one inheritance path to use to model both our mechanical and semantic needs. If you use it for one, you can't use it for the other. So doesn’t multiple inheritance solve this problem?No. Inheritance relationships should not cross domain boundaries (implementation domain vs application domain). Making CustomerGroup inherit from ArrayListbut also from (say) DemographicSegment tangles the two subdomains, confusing the taxonomy. The preferred (at least by me!) solution is to inherit from utility classes as much as necessary to implement your mechanical structures, then use these structures in domain classes via composition, not inheritance. Let me restate that: This is one of the most common beginner issues — because it’s so convenient! — and the reasons why it’s wrong are not often discussed in programming literature, so I’ll say it again: your application-domain classes should use implementation classes, not be one. Keep these taxonomies/domains separated. So when and how should we use inheritance? Using Inheritance WellThe most common - and beneficial - use of inheritance is for differential programming. We need a widget that is just like the existing Widget class, but with a few tweaks and enhancements. In this case, inherit away; it is appropriate because our subclass is still a widget, we want to reuse the entire interface and implementation from the superclass, and our changes are primarily additive. If you find that your subclass is removing things provided by the superclass, question inheriting from that superclass.Inheritance is most useful for grouping related sets of concepts, identifying families of classes, and in general organizing the names and concepts that describe the domain. As we delve deeper into the implementation of a system, we may find that our original generalizations about the domain concepts, captured in our inheritance hierarchies, are beginning to shred. Don’t be afraid to disassemble inheritance hierarchies into sets of complementary cooperating interfaces and components when the code leads you in that direction9. How to Decide: Composition or Inheritance?When you have a situation where either composition or inheritance will work, consider splitting the design discussion in two:
If you find that you are using a component to provide the vast majority of your functionality, creating forwarding methods on your class to call the component’s methods, exposing the component’s fields, etc., consider whether inheritance - for some or all of the desired behavior - might be more appropriate. There is no substitute for object modeling and critical design thinking. But if you must have some guidelines, consider these - What is the advantage of interface over inheritance?One key advantage of interfaces in a single inheritance language is that interfaces can be implemented on classes that do not share a common root. Another point is that interfaces allow what is known as interface inheritance rather than implementation inheritance.
What are the advantages of using inheritance?Benefits of Inheritance
Inheritance helps in code reuse. The child class may use the code defined in the parent class without re-writing it. Inheritance can save time and effort as the main code need not be written again. Inheritance provides a clear model structure which is easy to understand.
What are the advantages of using interfaces?Benefits of Using an Interface. The ability to define behavior that can be implemented by a group of unrelated classes without forcing them to share a common class hierarchy.. By implementing an interface, a class can perform in a role that is different from that dictated by its class hierarchy.. Are interfaces useful for inheritance?Interfaces Do Not Provide Multiple Inheritance
While interfaces may solve some of the same problems as multiple class inheritance, they are quite different animals. In particular: You cannot inherit variables from an interface. You cannot inherit method implementations from an interface.
|