2.1 Main Concepts of OOP
The foundation of the object-oriented approach to programming is the OOP paradigm. It's when all entities in the program are considered as objects. Objects are data + methods/functions that do something with that data.
You can also say that an object has a state and behavior. The state of an object is provided by its data stored in its internal variables. The behavior of an object is the sum of all actions taken by its methods.
There are thousands of objects in an average program, and millions in a large one. To manage the chaos, it was decided to organize objects into classes and classes into some hierarchy.
Every object has a class that spawns it. On one hand, a class is a sort of object template, on the other, it's an independent object with its own features (more on this below).
To better understand the concept of classes, check out the following definitions:
Class — a template or blueprint for creating objects that defines the attributes and methods common to all objects of this type. Classes allow organizing data and functions that work with that data into a coherent whole.
Object — an instance of a class. Each object has a state (defined by attributes) and behavior (defined by methods).
Encapsulation — involves hiding the internal implementation of a class and providing an interface for interacting with objects of that class. This helps protect the data and manage access to it.
Inheritance — allows one class (child) to inherit attributes and methods of another class (parent). This facilitates code reuse and simplifies its maintenance.
Polymorphism — enables the use of a single interface to work with objects of different classes. It's achieved through overriding methods in child classes inherited from parents.
Abstraction — involves identifying common characteristics of objects and creating classes that represent these common characteristics. This helps simplify complex systems and improve their comprehensibility.
If you understood even half of that — awesome. We'll go into more detail on each of these points later.
2.2 Abstraction
A good example of abstraction in real life is job descriptions in a company or organization. The job title is one thing, but the responsibilities of each specific position are another.
Imagine you're designing the structure of your future company. You might distribute the duties of a secretary among several other roles. You could split the executive director position into multiple independent roles: financial director, technical director, marketing director, and HR director. Or, for instance, you could combine the positions of office manager and recruiter into one.
From a programming perspective, abstraction is about properly dividing a program into objects. Typically any large program can be represented in dozens of ways as interacting objects. Abstraction allows you to select the main characteristics and leave out the secondary ones.
Abstraction is like strategy in warfare. A poor strategy can't be fixed with any amount of tactical genius.
2.3 Encapsulation
The goal of encapsulation is to improve the quality of interactions by simplifying them.
And the best way to simplify something is to hide all the complicated stuff from prying eyes. For example, if you're put in the cockpit of a Boeing, you won't immediately figure out how to operate it:
On the other hand, for airplane passengers, everything seems simpler: you buy a ticket, get on the plane, take off, and land. You can easily fly from continent to continent with just the skills of "buy a ticket" and "board the plane." All the complexities of getting the plane ready for flight, takeoff, landing, and various emergency situations are hidden from us. Not to mention satellite navigation, autopilot, and control centers in airports. And this makes our lives easier.
From a programming perspective, encapsulation is "hiding implementation". I like this definition. Our class might contain hundreds of methods and implement very complex behavior in different situations. But we can hide all its methods from prying eyes (surround their names with "__" on both sides), and leave just a few methods for interacting with other classes. Then all other classes in our program will see only three methods in this class, and will call only them. And all the complexities will be hidden inside the class, like a pilot's cockpit from happy passengers.
2.4 Inheritance
Inheritance has two sides: the programming side and the real-life side. From a programming perspective, inheritance is a special relationship between two classes. But it's much more interesting what inheritance is from a real-life perspective.
If we needed to create something in real life, we would have two solutions:
- create the thing we need from scratch, spending a lot of time and effort;
- create the thing we need based on something that already exists.
The most optimal strategy looks like this: take an existing good solution, tweak it a bit to suit our needs, and use it.
If we trace the history of humankind, it turns out that billions of years have passed since life began on the planet. And if we imagine that humans evolved from apes (based on apes), only a couple of million years have passed. Creating from scratch takes longer. Much longer.
In programming, there's also the possibility of creating one class based on another. The new class becomes a descendant (inheritor) of an existing class. This is really beneficial when there's a class that contains 80%-90% of the data and methods we need. We simply declare the appropriate class as the parent of our new class, and then our new class automatically gets all the data and methods of the parent class. Convenient, right?
2.5 Polymorphism
Polymorphism is a concept from programming. It describes a situation where different implementations are hidden behind a single interface. If you try to find parallels in real life, one such analogy would be the process of driving a car.
If a person can drive a truck, they can also drive an ambulance or a sports car. A person can drive a car regardless of what kind of car it is because they all have the same control interface: steering wheel, pedals, and gear shift lever. The internal design of the cars is different, but they all share the same control interface.
Returning to programming, polymorphism allows uniform treatment of objects of different classes (usually having a common ancestor) — something that's hard to overestimate. Its value increases as the program grows larger.
OOP — these are principles. Internal laws. Each of them in some way limits us, giving us great advantages in return when the program grows to a large size. The four principles of OOP are like the four legs of a chair. Remove at least one, and the whole system becomes unstable.
GO TO FULL VERSION