Java is all based on Object-oriented programming (OOP) paradigm. OOP is so integral to Java that it is best to understand its basic principles before you begin writing even simple Java programs.
Two Programming Paradigms
The world (or at al least the computer programs world) is governed by two programming paradigms that dictate how a program is constructed. The first paradigm is called process-oriented model and is characterized by writing programs that are conceptually organized around its code (“what is happening”, as a series of linear steps). The second paradigm, called object-oriented programming, organizes a program around its data (“who is being affected”) and a set of well-defined interfaces to that data. An object-oriented program can be characterized as data controlling access to the code.
The Four major OOP Principles
They are abstraction, encapsulation, inheritance, and polymorphism. Let’s take a look at these concepts now.
Abstraction
An essential element of object-oriented programming is abstraction, the way to manage complexity: Don't think in a system as the conjunction of multiple and complex components but as a well-defined object with its own unique behavior. When you drive a car, you don't need to know exactly about how the braking system actually works but the existence of a pedal that reduces the speed of the car when pressed.
A powerful way to manage abstraction is through the use of hierarchical classifications. It allows to model complex systems with different layers, breaking them into more manageable pieces.
“An abstraction denotes the essential characteristics of an object that distinguish it from all other kinds of object and thus provide crisply defined conceptual boundaries, relative to the perspective of the viewer.”— G. Booch
Cars are complex system
Every automobile is a really complex machine with millions of parts, each one with a specific functionality. If you try to understand all of them while trying to drive, you probably will never be able to drive a single mile.
Abstraction: Simple interfaces!
You can simplify the complex machine (car) with a simple and intuitive interface: 3 pedals, gearbox, and steering wheel. That's all you need to know to drive a car! You don’t need to know how these components are actually working, just the output when used: If press the brake pedal, the car will slow down. This is the beauty of abstraction.
Encapsulation
Encapsulation is the mechanism that binds together code and the data it manipulates, keeping both safe from outside interference and misuse. Another way of seeing encapsulations is a way to expose code (behavior) and data in a safe and controller environment, preventing unexpected side effects or external bad intentions.
The power of encapsulated code is to hide the complexity of the implementation, exposing an interface that everyone knows how to access it and thus use it regardless of the implementation details. In Java, the basis of encapsulation is the class, defining attributes and methods along with access modifiers to restrict the audience of each one.
Inheritance
Inheritance is the process by which one object acquires the properties of another object. This is important because it supports the concept of hierarchical classification. An object only needs to define those qualities that make it unique and inherit its general attributes from its parent.
Using animals as an example, we can describe them by commonly shared characteristics like size, skeletal system, reproduction type; and certain behavioral aspects like eat, breathe, and sleep. This description of attributes and behavior is the parent class definition for animals. We can go deeper describing a more specific animal types, such as mammals, defining more specific attributes that are only present for mammals, such as type of teeth and mammary glands. Mammals are a subclass of vertebrates, and vertebrates is a subclass of animals, inheriting all of the attributes from animal class.
Polymorphism
Polymorphism means one name, many forms; is a feature that allows one interface to be used for a general class of actions. This means that it is possible to design a generic interface to a group of related activities. This helps reduce complexity by allowing the same interface to be used to specify a general class of action. It is the compiler’s job to select the specific action (that is, method) as it applies to each situation.
There are two basic types of polymorphism:
- Overriding (Run-time polymorphism): The class defines a new way of performing some behavior that was already defined in a parent class.
- Overloading (compile-time polymorphism): The class add a new information to perform some behavior, without losing the original one.