Yet another OOP post
I continue to see questions like “Is Rust/Go/… object-oriented” answered with “No, because it doesn’t have inheritance”. This is my final word on this topic.
OOP exists to serve software engineering by facilitating good abstractions. This is achieved by making dependency inversion and polymorphism trivial.
If a language makes dependency inversion & polymorphism trivial, nobody need ask if it’s object-oriented again. The rest of the post unpacks this statement.
Imagine if to send or receive e-mails you had to start by first understanding electricity, then electronics, followed by binary encoding, instruction sets, microprocessors, drivers, kernels, operating systems, internet protocols and browsers — all of it and in that order.
The reason that is not our general experience is because we have invented abstractions which just means that within the boundary of said abstraction we understand precisely what is happening without needing to understand how it’s happening under the covers.
Good abstractions hide lower level details without impacting our understanding of the higher level in which we’re functioning. If however, we’re forced to get into the weeds then the abstraction is broken and it’s no longer a good one.
Dependency Inversion and Polymorphism
While we do not need to understand electronics or internet protocols to use e-mail we do absolutely depend on them being there, working as designed and constantly maintained by other humans to ensure our abstraction does not come crashing down.
So, does that make us slaves to Google if we’re using gmail, Virgin media if they’re providing the internet, Microsoft for the operating system and Dell for the computer?
No. We have much more power. If we don’t like the price Dell offers we can buy from Lenovo. Microsoft can be swapped for Mac. Gmail for Hotmail.
While we perhaps at this moment do depend on Google, Virgin media etc. they are obliged to conform to a contract that is independent from them regarding how e-mail works, how the internet works, how electronics work.
This is how we prevent monopolies and we allow for multiple of the same thing to exist — aka polymorphism.
And by making it trivial for me to switch from one provider to another, the power balance switches from the implementation provider to me, the customer. And that is dependency inversion.
And this concept which is so useful in our real life is also incredibly useful when designing software. This is what the OOP paradigm is really about. It allows you to make the business problem you’re solving the star of the show and not the underlying database or the framework.
Therefore, any programming language that allows for the definition of contracts (interfaces/traits…) and data structures (class/struct…) from which objects that can be created to satisfy them is object-oriented.
The irrelevant stuff
Encapsulation: this is just a design detail that emerges from the concept. When sending an email you want the details around the internet stack to be encapsulated (hidden) within the Send action and not have to be specified or manipulated. Btw, Java a supposed object-oriented language with it’s preponderance for getters/setters breaks just this. Imagine giving the e-mail sender the ability to set the e-mail server port number as part of message composition.
Inheritance: as useful as snow to an eskimo. There is enough research out there to suggest it can easily be harmful as helpful. Composition is generally a better way to achieve our desired abstraction goals.