DEV Community

Cover image for Object-Oriented Programming
Scofield Idehen
Scofield Idehen

Posted on

Object-Oriented Programming

OOP

OOP stands for Object-Oriented Programming. It is a programming model that organizes code into objects that are instances of classes, where an object bundles together data and methods, allowing both to operate as one integrated unit.

In Java language, OOP is used to create objects from classes. A Java class acts as a blueprint that defines what data and methods each object will contain. When you create an object from that class, it is called an instance of that particular class.

For example, a Person class could be defined by properties like name, age, and abilities such as walk() and talk().

The Person class becomes a template for creating instances of people like John and Mary, which are objects of the template class Person.

A core difference between OOP and Procedural Programming is the approach to structuring code. Procedural programming focuses on writing procedures or functions that operate on data, whereas OOP emphasizes the organization of code into objects that encapsulate data and behavior.

The key pillars of OOP that support it are Inheritance, Polymorphism, Abstraction, and Encapsulation. These core concepts are explored below.

Inheritance

Inheritance in Java language allows a child class to inherit data and behaviors from a parent class. It enables code reuse by allowing child classes to reuse logic from parent classes.

Inheritance creates hierarchical relationships between classes. Child classes inherit shared parent class logic and can override or extend the inherited capabilities for specific subclass needs.

For example, the Child class can inherit from the Person class, taking on specific attributes like name and age, and override some other inherited capabilities like walk().

You can use the extends keyword to implement Inheritance in Java. The use of inheritance is realized when the programmer does not wish to define the same set of methods or fields for the new class as an Inheritance links the child and parent classes. The child class inherits and builds on the data & behaviors of the parent.

![Inheritance first example](https://mate-academy-images.s3.eu-central-1.amazonaws.com/inheritance_4b937162da.png)

Example of Inheritance:

    class Parent {

       // fields
       // methods

    }

    class Child extends Parent {

       // already supports the methods and fields of the `Parent` class
       // additional features

    }
Enter fullscreen mode Exit fullscreen mode

Composition and Aggregation are two types of relationships often confused with Inheritance.

  • Composition is a "belongs-to" type of relationship. It means that one of the objects is part or member of the other object. Alternatively, we often call it a "HAS-A" relationship (as opposed to an "IS-A" relationship, which is inheritance). These objects' lifecycles are tied. It means that if we destroy the owner object, its member also will be destroyed. For example, the room is destroyed along with the building.

  • Aggregation is similar to composition. However, it doesn't involve owning. As a result, the lifecycles of the objects aren't tied: everyone can exist independently of each other. For example, take a car and its wheels. We can take off the wheels, and both still exist.

Method Overriding

Method overriding allows a subclass to provide a different implementation of a method already defined in its superclass. It allows a subclass to modify the behavior of an inherited method according to its specific requirements.

To override a method, the subclass must declare a method with the same name, return type, and parameter list as the method in the superclass. The overriding method should also be marked with the @Override annotation to ensure it correctly overrides a superclass method.

    class Vehicle {
       public void drive() {
           System.out.println("Driving a vehicle...");
       }
    }

    class Car extends Vehicle {
       @Override
       public void drive() {
           System.out.println("Driving a car...");
       }
    }

    class Bike extends Vehicle {
       @Override
       public void drive() {
           System.out.println("Riding a bike...");
       }
    }
Enter fullscreen mode Exit fullscreen mode

The objects of the Vehicle, Car, and Bike classes, when created, can call the drive() on each object. The JVM determines the actual type of the object at runtime and executes the corresponding overridden method.

    Driving a vehicle...
    Driving a car...
    Riding a bike...
Enter fullscreen mode Exit fullscreen mode

Please note: final, static, and private methods cannot be overridden.

Method Overloading

Method overloading allows multiple methods with the same name but different parameter lists to coexist within a class. It provides a way to define methods that perform similar tasks but with different input parameters.

    class Calculator {
       public int add(int a, int b) {
           return a + b;
       }

       public double add(double a, double b) {
           return a + b;
       }

       public int add(int a, int b, int c) {
           return a + b + c;
       }
    }
Enter fullscreen mode Exit fullscreen mode

The Calculator class can call the add() methods with different arguments, as shown above.

    Calculator calculator = new Calculator();

    int sum1 = calculator.add(2, 3); // 5
    double sum2 = calculator.add(2.5, 3.7); 6.2
    int sum3 = calculator.add(2, 3, 4); // 9
Enter fullscreen mode Exit fullscreen mode

Polymorphism

Polymorphism is the ability of objects of different classes to be treated as objects of a common superclass. It allows other objects to respond differently to the same message (method call). Polymorphism enables code flexibility and extensibility by providing a common interface for interacting with objects of different types.

Polymorphism has two types: Compile-time polymorphism (static binding) and Runtime polymorphism (dynamic binding). Method overloading is an example of static polymorphism, while method overriding is an example of dynamic polymorphism.

An important example of polymorphism is how a parent class refers to a child class object. Any object that satisfies more than one "IS-A" relationship is polymorphic. For example, let's consider a class Vehicle and let MotorBike be a subclass of Vehicle. So, any motorBike IS vehicle. Here, MotorBike satisfies the "IS-A" relationship for its type and superclass `Vehicle.

Abstraction

Abstraction shows only essential attributes and hides unnecessary information. The primary purpose of abstraction is to hide unnecessary details from the users. Abstraction selects data from a larger pool to show the user. It helps in reducing programming complexity.

The abstract keyword is a non-access modifier used for classes and methods:

The abstract keyword is a non-access modifier used for classes and methods:

  • An abstract class is a restricted class that cannot be used to create objects (to access it, it must be inherited from another class);
  • An abstract method can only be used in an abstract class, and it does not have a body. The subclass provides the body.

Example of abstraction:

(...)

Task: Get Drinks

Let's move on! Let's learn how to implement more complex loops.

One day, the host at a wedding decided to entertain the guests and set a rule: each guest who comes makes a toast, and all guests drink for the health of the newlyweds.

For example:

  • First guest arrives — Only one drink is needed;
  • Second guest — Two drinks are required;
  • Third guest — Three more drinks, and so on.

If 5 guests show up, 15 drinks are required (1 + 2 + 3 + 4 + 5).

If 10, then 55 drinks (1 + 2 + 3 + ... + 10).

Implement the getDrinks function that accepts numberOfGuests — Find out how many guests will be at the wedding and returns the required number of drinks.

More examples:

java
getDrinks(0); // 0 - no guests - no drinks
getDrinks(2); // 1 + 2 = 3
getDrinks(6); // 1 + 2 + 3 + 4 + 5 + 6 = 21

Check the Sum of Numbers From 1 to n theory section to determine how to sum numbers in a loop.

<details>
 <summary>Hint</summary>

 - If the `numberOfGuests === 0` — return `0`.
 - If not, create a variable to count the required portions, for example, `let numberOfPortions = 0`.
 - Create a `for` loop from `1` to `numberOfGuests`.
 - Increase the `numberOfPortions` by the current number of guests at each loop iteration.
 - Return the result after the loop.
</details>
Enter fullscreen mode Exit fullscreen mode

Top comments (0)