The 4 pillars of Object-Oriented Programming
Tags: java, programming
Published: 2024-01-24 10:23:49

**Encapsulation**
Encapsulation is one of the four fundamental principles of object-oriented programming (OOP), and it involves bundling the data (attributes) and methods (functions) that operate on the data into a single unit known as a class. The main idea behind encapsulation is to hide the internal details of an object and provide a well-defined interface through which the outside world can interact with the object.

Key concepts of encapsulation:

_Access Modifiers_:
Encapsulation often employs access modifiers (such as private, protected, and public in Java or C++) to control the visibility of a class's members. By making certain attributes or methods private, they are accessible only within the class, ensuring that the internal state is not directly manipulated from outside the class.

_Getter and Setter Methods_:
Instead of allowing direct access to the internal attributes, encapsulation encourages the use of getter and setter methods. Getter methods provide controlled access to the values of private attributes, while setter methods allow the class to validate and control the assignment of new values.

_Data Hiding_:
Encapsulation enables data hiding, which means that the internal representation of an object is hidden from the outside. This helps prevent unintended interference and ensures that the object's state is only modified in a controlled manner through the defined methods.

_Information Hiding_:
Along with data hiding, encapsulation also involves information hiding. It conceals the complex implementation details of a class and exposes only what is necessary for the outside world to use. This simplifies the usage of the class and reduces dependencies on its internal structure.

_Example_:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4xmi1bh5id9tm86z3g4m.png)


**Inheritance**
Inheritance is one of the key principles of object-oriented programming (OOP) that allows a new class (subclass or derived class) to inherit the characteristics and behaviors of an existing class (superclass or base class). Inheritance promotes code reuse and the creation of a hierarchy of classes, where a subclass can leverage the features of its superclass.

Here are the key concepts of inheritance:

_Base Class (Superclass)_:
The base class, also known as the superclass, is the existing class that contains common attributes and methods. It serves as a blueprint for creating new classes.

_Derived Class (Subclass_):
The derived class, also known as the subclass, is the new class that inherits attributes and methods from the base class. It can also have its own additional attributes and methods or override existing ones.

_"is-a" Relationship_:
Inheritance establishes an "is-a" relationship between the subclass and the superclass. For example, a Dog "is-a" type of Animal. This relationship indicates that a Dog shares common characteristics with an Animal but may have additional or specialized behaviors.

_Code Reusability_:
Inheritance promotes code reusability by allowing the subclass to inherit the properties and behaviors of the superclass. This reduces redundancy in code and makes it easier to maintain and extend the system.

_Method Overriding_:
Subclasses can override (provide a new implementation for) methods inherited from the superclass. This allows customization of behavior in the subclass while maintaining a consistent interface.

_Example_:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/kwvi0rxlmmaw50znbaxc.png)

**Polymorphism**
Polymorphism is one of the fundamental principles of object-oriented programming (OOP) that allows objects of different types to be treated as objects of a common base type. This concept enables a single interface or method signature to represent different types of objects, providing flexibility and extensibility in code.

There are two main types of polymorphism: compile-time (or static) polymorphism and runtime (or dynamic) polymorphism.

_Compile-time Polymorphism (Method Overloading)_:
Compile-time polymorphism occurs when multiple methods with the same name but different parameter lists (number or types of parameters) exist within the same class. The compiler determines which method to call based on the method signature during the compile-time.

_Runtime Polymorphism (Method Overriding)_:
Runtime polymorphism occurs when a subclass provides a specific implementation for a method that is already defined in its superclass. This is achieved through method overriding.

_Polymorphism through Interfaces_:
Interfaces in Java also contribute to polymorphism by allowing multiple classes to implement the same interface. Objects of different classes can be treated polymorphically if they implement the same interface.

_Example_:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b8xyrhgfa6yakwmdzoy5.png)

**Abstraction**
Abstraction is a fundamental principle in object-oriented programming (OOP) that involves simplifying complex systems by modeling classes based on the essential properties and behaviors relevant to the problem at hand, while ignoring or hiding the unnecessary details. It allows developers to create a high-level model that represents the core aspects of an object or system, without exposing all the intricate implementation details.

Key concepts of abstraction include:

_Abstract Classes and Interfaces_:
Abstraction is often implemented through abstract classes and interfaces. Abstract classes are classes that cannot be instantiated on their own and may contain abstract methods (methods without a concrete implementation). Interfaces declare a set of method signatures without providing implementations. Both abstract classes and interfaces define a contract that concrete classes must fulfill.

_Hiding Implementation Details_:
Abstraction involves hiding the internal implementation details of a class and exposing only what is necessary for the outside world to interact with. This allows developers to focus on the essential aspects of an object and abstract away the complexity.

_Simplifying Complexity_:
Abstraction simplifies complex systems by breaking them down into manageable and understandable components. It allows developers to work with a higher-level representation of objects and systems, making the design and maintenance of code more straightforward.

_Focus on What, Not How_:
Abstraction encourages developers to focus on "what" an object does rather than "how" it achieves its functionality. This separation of concerns improves the clarity of code and makes it easier to understand and maintain.

_Code Reusability_:
Abstraction promotes code reusability by defining common interfaces or abstract classes that can be implemented by multiple concrete classes. This reduces redundancy and allows for a more modular and extensible codebase.

_Example_:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jre6f0f8f8xo9lilsfq1.png)