In OOP inheritance is generally frowned upon. There may be some practical aspects to this, but ideologically.. This isn’t a practice that should exist. And where to draw the inspiration for this discussion if not from Mathematics?
Abstractions in Math and Programming
These days pure math is mostly (?) a study of abstractions. Subjects like Abstract Algebra are all about a) finding commonalities between concrete branches of mathematics, b) creating abstractions out of those commonalities and c) deriving properties based on the abstractions.
This matches Interfaces and Polymorphism perfectly: an Interface is an abstraction, and we don’t need to know anything about implementations to build logic based on it. We only need the guarantees (the API) of the abstraction. For instance we can go through the elements of Iterable, regardless of whether it’s a List, a Set or if we read words one by one from a file.
What if we need the number of elements behind an Iterable? If all the implementations can provide it, then sure - our abstraction can have additional property. But when reading words from a file we can’t know how many words there are until we fully read it, so this is incompatible at least with one implementation. We have 2 choices: not consider WordReader an Iterable, or leave Iterable unchanged and simply add another abstraction with more methods (aka Interface Segregation Principle).
How do we decide? We could create an Interface for each method that we add, and… overwhelm ourselves with all the possible combinations 🤔 How do mathematicians decide which abstractions to create? Simple: if it’s possible to do something useful with properties A/B/C (derive other properties X/Y/Z), then that’s a useful abstraction.
Programmers do something similar: if there are many places where we need methods A/B/C but we never need A or A/B alone, then A/B/C it is.
But what about Inheritance?
Notice, that we never discussed Inheritance. That’s because there’s no such thing in math. In principle, if Integer Addition can be used in 100 contexts and we need 100 combinations of properties, then Integer Addition “implements” 100 interfaces. So 1 implementation, N interfaces.
In programming Inheritance is NOT about abstractions. It’s about reusing code between implementations (3 implementations have 1 identical method, so let’s create an abstract class).
Abstractions on the other hand are about reusing the client code - same client code handles 3 implementations.
And that’s the ideological reason why Inheritance is useless. You can always replace it with composition - move the common method elsewhere and just invoke it from the 3 implementations. Of course we’ll have to explicitly declare the same methods in every implementation, and we like counting the lines of code so much… 🙂 So practical considerations need to be considered too, but that's a separate discussion. Still, inheritance should not be considered in the same context with with abstractions and interfaces.
To get notifications about new posts, Watch this repository.
In OOP inheritance is generally frowned upon. There may be some practical aspects to this, but ideologically.. This isn’t a practice that should exist. And where to draw the inspiration for this discussion if not from Mathematics?
Abstractions in Math and Programming
These days pure math is mostly (?) a study of abstractions. Subjects like Abstract Algebra are all about a) finding commonalities between concrete branches of mathematics, b) creating abstractions out of those commonalities and c) deriving properties based on the abstractions.
This matches Interfaces and Polymorphism perfectly: an Interface is an abstraction, and we don’t need to know anything about implementations to build logic based on it. We only need the guarantees (the API) of the abstraction. For instance we can go through the elements of Iterable, regardless of whether it’s a List, a Set or if we read words one by one from a file.
What if we need the number of elements behind an Iterable? If all the implementations can provide it, then sure - our abstraction can have additional property. But when reading words from a file we can’t know how many words there are until we fully read it, so this is incompatible at least with one implementation. We have 2 choices: not consider WordReader an Iterable, or leave Iterable unchanged and simply add another abstraction with more methods (aka Interface Segregation Principle).
How do we decide? We could create an Interface for each method that we add, and… overwhelm ourselves with all the possible combinations 🤔 How do mathematicians decide which abstractions to create? Simple: if it’s possible to do something useful with properties A/B/C (derive other properties X/Y/Z), then that’s a useful abstraction.
Programmers do something similar: if there are many places where we need methods A/B/C but we never need A or A/B alone, then A/B/C it is.
But what about Inheritance?
Notice, that we never discussed Inheritance. That’s because there’s no such thing in math. In principle, if Integer Addition can be used in 100 contexts and we need 100 combinations of properties, then Integer Addition “implements” 100 interfaces. So 1 implementation, N interfaces.
In programming Inheritance is NOT about abstractions. It’s about reusing code between implementations (3 implementations have 1 identical method, so let’s create an abstract class).
Abstractions on the other hand are about reusing the client code - same client code handles 3 implementations.
And that’s the ideological reason why Inheritance is useless. You can always replace it with composition - move the common method elsewhere and just invoke it from the 3 implementations. Of course we’ll have to explicitly declare the same methods in every implementation, and we like counting the lines of code so much… 🙂 So practical considerations need to be considered too, but that's a separate discussion. Still, inheritance should not be considered in the same context with with abstractions and interfaces.
To get notifications about new posts, Watch this repository.