OOP - 4 Pillars in Java
Tags: java, programming, oop, beginners
Published: 2023-11-29 21:16:14

## What is OOP in general?

OOP stands for object-oriented programming. The word object-oriented is a combination of two terms, _object_ and _oriented_. The dictionary meaning of an object is "an entity that exists in the real world", and oriented means "interested in a particular kind of thing or entity". So, in basic terms, OOP is a programming pattern that is built around objects and entities, thus it is called like that.

## The structure of OOP

The structure of OOP consists of 4 parts: classes, attributes, methods and objects. **Classes** are blueprints of objects, attributes and methods, they are like templates for objects. **Attributes** are properties of classes that represent the state of an object, they define the characteristics of it. **Methods** are functions defined inside the scope of a class, they represent the behavior of an object. And finally, **objects** are instances of a class created using the class as a template. Each object has its own set of attributes and can use the methods defined in the class. For example, let's say we have a Car _class_. It can have _attributes_ like color, model, speed. It can have _methods_ like startEngine(), stopEngine(), brake(). Finally, it can have _instances_ like Car1, Car2, Car3.

You can see an example code in Java emphasizing OOP structure points below.

```java
public class Car {
    private String color;
    private String model;
    private int speed;
    private boolean engineStarted;

    public Car(String color, String model, int speed) {
        this.color = color;
        this.model = model;
        this.speed = speed;
        this.engineStarted = false;
    }

    public void startEngine() {
        if (!engineStarted) {
            System.out.println("Engine started.");
            engineStarted = true;
        } else {
            System.out.println("Engine is already running.");
        }
    }

    public void stopEngine() {
        if (engineStarted) {
            System.out.println("Engine stopped.");
            engineStarted = false;
        } else {
            System.out.println("Engine is already off.");
        }
    }

    public void brake() {
        if (speed > 0) {
            System.out.println("Brake applied. Slowing down.");
            speed = 0;
        } else {
            System.out.println("Car is already stationary.");
        }
    }
```

## 4 pillars of OOP

4 pillars of OOP are Inheritance, Polymorphism, Encapsulation and Abstraction. 
 
**Inheritance** allows a class(subclass or derived class) to inherit the properties and behaviors of another class(superclass or base class). It promotes code reusibility and establishes a relationship between classes. For example, let's say we have a class Animal. Dog, Cat and Cow classes can be inherited(subclasses) from Animal and get all its properties(methods and attributes) as they are all animals.

You can see an example code in Java emphasizing _Inheritance_ in OOP below.

```java
// Superclass
class Animal {
    private String name;

    public Animal(String name) {
        this.name = name;
    }

    public void eat() {
        System.out.println(name + " is eating.");
    }

    public void sleep() {
        System.out.println(name + " is sleeping.");
    }
}

// Subclass 1
class Dog extends Animal {
    public Dog(String name) {
        super(name);
    }

    public void bark() {
        System.out.println("Woof! Woof!");
    }
}

// Subclass 2
class Cat extends Animal {
    public Cat(String name) {
        super(name);
    }

    public void meow() {
        System.out.println("Meow!");
    }
}

// Subclass 3
class Cow extends Animal {
    public Cow(String name) {
        super(name);
    }

    public void moo() {
        System.out.println("Moo!");
    }
}
```

**Polymorphism** allows objects of different classes to be treated as objects of a common base class. This enables a single interface to represent different types of objects, promoting flexibilty and extensibility. Using the example from the previous point, you can see an altered code example in Java emphasizing _Polymorphism_ below.

```java
// Superclass
class Animal {
    private String name;

    public Animal(String name) {
        this.name = name;
    }

    public void makeSound() {
        System.out.println(name + " makes a generic animal sound.");
    }
}

// Subclass 1
class Dog extends Animal {
    public Dog(String name) {
        super(name);
    }

    @Override
    public void makeSound() {
        System.out.println(name + " barks: Woof! Woof!");
    }
}

// Subclass 2
class Cat extends Animal {
    public Cat(String name) {
        super(name);
    }

    @Override
    public void makeSound() {
        System.out.println(name + " meows: Meow!");
    }
}

// Subclass 3
class Cow extends Animal {
    public Cow(String name) {
        super(name);
    }

    @Override
    public void makeSound() {
        System.out.println(name + " moos: Moo!");
    }
}
```

**Encapsulation** is the bundling of data(attributes) and methods(functions) that operate on the data into a single unit known as a class. We use _access modifiers_(public, private, protected) to control access to the attributes and methods. 

You can see an example code in Java emphasizing _Encapsulation_ below.

```java
public class Car {
    private String model;
    private int year;

    public Car(String model, int year) {
        this.model = model;
        this.year = year;
    }

    public String getModel() {
        return model;
    }

    public int getYear() {
        return year;
    }
}
```
Here, the Car class encapsulates the data(model and year) by making them private and provides public methods(getModel(), getYear()) to access these attributes. This way, you control access to the internal state of the object.

**Abstraction** is hiding the complex reality while exposing only the essential parts. Abstract classes and interfaces are used to achieve abstraction. For example, an average car-user does not really care how the car was made, what forces are necessary for it to move or how the brake is constructed to work properly. However, the automobile engineer does care about all this stuff, just because it is their job.

You can see a code example in Java emphasizing _Abstraction_ below.

```java
public abstract class Shape {
    abstract double area();
}

public class Circle extends Shape {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    @Override
    double area() {
        return Math.PI * radius * radius;
    }
}
```

Here, the Shape class is abstract and has an abstract method area(). The Circle class extends Shape and provides a concrete implementation of the area() method. Abstraction allows you to define a common interface(Shape) while leaving the specific implementation details to the subclass.

## The end :D

In this post we covered the concept of Object-oriented programming, its structure and 4 pillars, that include Inheritance, Polymorphism, Encapsulation and Abstraction. You can see the video version of this material on my YouTube channel: https://youtu.be/P9B2cD4MNlI?si=1rB82S5xgzrYVpwx