I agree with "anti-inheritance" as a general guideline, but its adherents have to recognize the significant practical upsides of inheritance in many situations.
Imagine you have an interface with 20+ methods, such as the List interface. And you want to create a new implementation of this interface, which is almost identical to an existing implementation, except for one tiny difference. Example, you want an CustomArrayList implementation that doesn't allow the number 666 to be populated into the list.
With inheritance, you can accomplish this in just a few lines of code. Extend the existing implementation, and override just the methods that need to be overridden.
Whereas with composition, you now need to manually implement all 20+ methods in the interface, just to make the pass-through call. This adds a tremendous amount of boilerplate to the code.
Depending on how many methods are in the interface and how invasive the changes are, this boilerplate is sometimes worth it and sometimes not worth it. Ideally, languages will add built-in support to facilitate this pattern without the associated verbosity. But until then, people will continue to use inheritance just because of how much less verbose it is.
>Whereas with composition, you now need to manually implement all 20+ methods in the interface, just to make the pass-through call. This adds a tremendous amount of boilerplate to the code.
Inheritance is not necessary for this. The traditional way of achieving this in functional languages is to use a closure to return an object/record. Instead of brittle inheritance, just pass this object to another function that returns an object modified however you want it. Objects can be combined too, achieving the same goal as multiple inheritance, but less dangerous. Simple, easy, succinct, composable.
I agree that inheritance is not necessary for this, if languages provided better built-in support for the composition pattern. I was referring to the downsides of using composition in today's "enterprise" languages like Java.
Ideally, languages will add built-in support to facilitate this pattern without the associated verbosity. But until then, people will continue to use inheritance just because of how much less verbose it is.
Well, you can somehow achieve a part of it in Python with implementing magic __getattribute__ method:
class CustomArrayList (object):
def __init__(self):
self.list = ArrayList()
def add(self, item):
if item == 666:
raise
self.list.add(item)
def __getattribute__(self, key):
"""For rest of the methods use them as they are.
"""
try:
attr = object.__getattribute__(self, key)
except AttributeError:
attr = object.__getattribute__(self.list, key)
return attr
However, most probably no one will like you if you use this method :)
I have used inheritance in a way to make accessing code more seamless and easier for development. But without inheritance, I end up with a lot of boilerplate code, imports, etc...
Doesn't duplication go against the DRY principle? I know you are saying "wrong inheritance", but some people are saying all inheritance is wrong...
My little rule of thumb is to inherit if the new implementation is a 'pure' over the inherited class.
That is, I'm not introducing any _new_ changes to the state of the class.
Code generation tends to result in bloated binaries and excessive runtime memory consumption (unless your compiler is especially clever about optimizing out the redundancies).
Imagine you have an interface with 20+ methods, such as the List interface. And you want to create a new implementation of this interface, which is almost identical to an existing implementation, except for one tiny difference. Example, you want an CustomArrayList implementation that doesn't allow the number 666 to be populated into the list.
With inheritance, you can accomplish this in just a few lines of code. Extend the existing implementation, and override just the methods that need to be overridden.
Whereas with composition, you now need to manually implement all 20+ methods in the interface, just to make the pass-through call. This adds a tremendous amount of boilerplate to the code.
Depending on how many methods are in the interface and how invasive the changes are, this boilerplate is sometimes worth it and sometimes not worth it. Ideally, languages will add built-in support to facilitate this pattern without the associated verbosity. But until then, people will continue to use inheritance just because of how much less verbose it is.