The Four Main Object Oriented Programming Concepts in Java With Examples

By The Four Main Object Oriented Programming Concepts in Java With Examples

Hi buddy, today I will explain what OOP (Object-oriented programming) in Java is. Java is one of the most popular and widely used programming language and platform. In my article The Best Way to Learn Java Programming Language, I said that it could be tricky to learn Java because you will encounter complex concepts like objects, polymorphism, inheritance, etc. Now I will help you understand these concepts.

I hope that by now, you know the basic structure of a java program. You must learn the exact structure of a Java program before proceeding with more advanced Java programming concepts like OOP.

Java is one of the hottest programming languages which is highly supported. It is a class-based object-oriented programming language and is built around objects. The OOP improves the readability and usability of a java program as well as making it less complicated. 

List of OOP Concepts in Java 

The OOP concepts are the main idea behind Java's Object-Oriented Programming. They include: 

  1. Abstraction.
  2. Encapsulation.
  3. Inheritance.
  4. Polymorphism. 

These concepts allow us to create specific interactions between Java objects. They make it possible to reuse code without compromising security or making a Java program less readable. Understanding them very well is the key to understanding how java works.

Here are the four main principles in more detail.

1. Abstraction

Abstraction merely is using straight-forward things to represent complexity. Its main goal is to hide unnecessary details from the user. It helps one to implement more complex details using the provided abstraction without even knowing the hidden complexity. It is not limited to object-oriented programming. Hence, you can find it in real life. 

a. Abstraction in the real world

Driving a car is an excellent example of abstraction. You need to know how to drive a car. You need to start the car and use the steering wheel and then drive to your destination.

You don't need to know how the car is working internally. You don't need to understand how the engine starts or how the wheels turn.

There was an engineer somewhere who worried about that and created a simple car dashboard which hides all the complexity. You use the dashboard without applying any knowledge about the internal implementation.

Programmers use the same concepts in Object-oriented programming languages like Java

b. Abstraction in Java

In OOP programming, you can hide the internal implementation by using abstract classes or interfaces. In the interfaces, you define method names and parameter list, without the body, and let each class implement them in their way.

This is what abstraction does:

  1. Hides the underlying complexity of code.
  2. Provides flexibility to change the implementation of the abstract behavior.
  3. Helps avoid code repetition.
  4. Presents only the name and parameter list of internal functionality.

In Java, we can achieve partial abstraction by using abstract classes and achieve total abstraction (100%) by using interfaces.

a. Abstract classes

An abstract class is a superclass that cannot be instantiated. You need to create an instance of its subclass if you want to create a new object. These classes have both abstract and concrete methods. Abstract methods only declare the method name and parameter list, while concrete methods declare method bodies as well. You create abstract classes by defining the abstract keyword.

The following is an example of an abstract class called Vehicle.

abstract class Vehicle {
    // abstract methods
    abstract void move();
    abstract void carry();
    // concrete method
    void label() {
        System.out.println("Vehicle's Data:");
    }
}

Now we can create two more classes: Bus and Truck. Both of them implement their functions for move() and carry() abstract methods.

class Bus extends Vehicle {
    void move() {
        System.out.println("Moves by petrol.");
    }
    void carry() {
        System.out.println("Carries passengers");
    }
}
class Truck extends Vehicle {
    void move() {
        System.out.println("Moves by diesel.");
    }
    void carry() {
        System.out.println("Carries goods.");
    }
}

Now we test them using TestBus and TestTruck classes. Both call the one concrete (label()) and the two abstract (move() and carry()) methods.

class TestBus {
    public static void main(String[] args) {
        Vehicle bus = new Bus();
        bus.label();
        bus.move();
        bus.carry();
    }
}
class TestTruck {
    public static void main(String[] args) {
        Vehicle truck = new Truck();
        truck.label();
        truck.move();
        truck.carry();
    }
}

The following is the output when we run the code. The concrete method was called from the abstract class while the two abstract methods were called from Bus() and Truck() respectively.

run:
Vehicle's Data:
Moves by petrol.
Carries passengers
run:
Vehicle's Data:
Moves by diesel.
Carries goods.

b. Interfaces

Interfaces are also known as blueprints of classes. An interface provides 100% abstraction. It can only have static, final and public fields and abstract methods. Remember a java class can only inherit from one class, i.e., you extend only one class, but Java interfaces allow us to implement multiple inheritances. This is due to the fact that a class can implement more than one interface. The keyword implements is used to access an interface.

The following is an example of two interfaces. The interface Vehicle has one abstract method. The interface Bicycle has one abstract method and one static field.

interface Vehicle {
    public void applyBreaks();
}
interface Bicycle {
    int wheels = 2;
    public void cycle();
}

The class MountainBike implements the two interfaces and defines its own functionality for the abstract methods.

class MountainBike implements Vehicle, Bicycle {
    @Override
    public void applyBreaks() {
        System.out.println("Mountain Bike stops when breaks are applied");
    }
    @Override
    public void cycle() {
        System.out.println("Has a speed of 50KMPH");
    }
}

In the TestMountainBike, we create a new MountainBike object and call it mBike and print out all the fields and methods to the console.

class TestMountainBike {
    public static void main(String[] args) {
        MountainBike mBike = new MountainBike();
        mBike.applyBreaks();
        mBike.cycle();
        System.out.println("Number of wheels: " + Bicycle.wheels);
    }
}

Because static fields do not belong to any specific object but a whole class, you access them from the Bicycle interface instead of mBike object.

The following is the output when we run the code.

run:
Mountain Bike stops when breaks are applied
Has a speed of 50KMPH
Number of wheels: 2

2. Encapsulation

This means protecting data in a class from system-wide reach. As its name suggests, it safeguards the internal contents of a class like a real-life capsule. In java, we achieve encapsulation by keeping the members of a class (methods and variables) private, then accessing them through public setter and getter methods. In this way, we can reuse the objects like code components or variables without allowing open access to the data system-wide. Java Beans are examples of fully encapsulated classes.

Encapsulation in Java

  1. Encapsulation restricts direct access to members of a class.
  2. Fields (variables) are set to private
  3. Each field has a getter and setter method.
  4. Getter methods let us get the value of the field, whereas setter methods lets us change the value of a field.

This following is an example of encapsulation

To achieve encapsulation in Java, we declare the fields as private and provide access to them using getter and setter methods.

The class Vehicle below is fully encapsulated. It has three fields which are private, and each of them has a setter and a getter method.

class Vehicle{
    private String model;
    private int numberOfWheels;
    private double averageSpeed;
    public String getModel() {
        return model;
    }
    public void setModel(String model) {
        this.model = model;
    }
    public int getNumberOfWheels() {
        return numberOfWheels;
    }
    public void setNumberOfWheels(int numberOfWheels) {
        this.numberOfWheels = numberOfWheels;
    }
    public double getAverageSpeed() {
        return averageSpeed;
    }
    public void setAverageSpeed(double averageSpeed) {
        this.averageSpeed = averageSpeed;
    }
    
}

To test we use TestVehicle class. First, we set the values for each field using the setter methods and then print out the values using the getter methods.

class TestVehicle{
    public static void main(String[] args) {
        Vehicle myVehicle = new Vehicle();
        myVehicle.setModel("MountainBike");
        myVehicle.setAverageSpeed(45.5);
        myVehicle.setNumberOfWheels(2);
        System.out.println("Model : "+myVehicle.getModel());
        System.out.println("Average Speed : "+myVehicle.getAverageSpeed());
        System.out.println("Number of wheels : "+myVehicle.getNumberOfWheels());
    }
}

The following is the output of our code.

run:
Model : MountainBike
Average Speed : 45.5
Number of wheels : 2

3. Inheritance

Inheritance is a special feature of OOP in Java. Just like in Biology, where the children inherit the characteristics of their parents, in OOP, we have a subclass (child class) inheriting from the superclass (parent class). This feature allows us to create new classes that share some of the attributes of the existing classes.  It is a great way to achieve code reusability because it lets us build upon previous work without reinventing the wheel.

Inheritance in Java

  1. A sub-class can extend another class (super-class) by inheriting its features.
  2. Improves code re-usability.
  3. Multilevel inheritance is allowed meaning a child class can have its own child class as well.
  4. Multiple inheritances are not allowed in Java (a class cannot extend more than one class).

The following is an example of encapsulation

In java, we need to use extends keyword to create a child class.

In the example below the MountainBike class extends the Bicycle parent class. It inherits all the fields and methods, plus defines two more fields that belong to MountainBike only.

class Bicycle {
    public int wheels = 2;
    public void cycle() {
        System.out.println("Cycling....");
    }
}
class MountainBike extends Bicycle {
    public String name = "Mountain Bike";
    public double avgSpeed = 45.5;
}

The TestMountainBike class creates a new MountainBike object and prints out all the information of the MountainBike. Both the inherited methods and extra fields.

class TestMountainBike {
    public static void main(String[] args) {
        MountainBike mBike = new MountainBike();
        System.out.println("Name: " + mBike.name);
        System.out.println("Average Speed: " + mBike.avgSpeed);
        System.out.println("Number of Wheels: " + mBike.wheels);
        mBike.cycle();
    }
}

The following is the output of our code.

run:
Name: Mountain Bike
Average Speed: 45.5
Number of Wheels: 2
Cycling....

4. Polymorphism

Polymorphism is the ability to perform one action in several ways. It lets programmers use the same word to mean different things in different contexts. Java provides two forms of polymorphism: method overloading and method overriding. Method overloading happens when more than one method with a similar name appears in a class. When they are called, they are differentiated by the number, order, and types of their parameters or arguments. Method overriding happens when a child class overrides a method of its parent.

Polymorphism in Java

  1. Several methods in a class use the same name.
  2. Different methods of the same name can be called from the object.
  3. All Java objects can be considered polymorphic because, at the minimum, they are of their own type and instances of the Object class.
  4. Method overloading is static polymorphism, whereas method overriding is dynamic polymorphism.

a. Static polymorphism

Method overloading is static polymorphism. Method overloading means having several methods with the same name within a class. The difference is the number, order, and types of their parameters.

Example code: The class Bicycle has three cycle() methods.

class Bicycle {
    public void cycle() {
        System.out.println("The Bicycle is cycling.");
    }
    public void cycle(double speed) {
        System.out.println("The Bicycle is cycling at " + speed + " kilometers per hour.");
    }
    public void cycle(String name, double speed) {
        System.out.println("The " + name + " is cycling " + speed + " kilometers per hour.");
    }
}

The test class creates a new Bicycle object and calls the cycle() method three times. Fist, without any parameter, secondly, with one parameter and finally with two parameters.

class TestBicycle {
    public static void main(String[] args) {
        Bicycle mBike = new Bicycle();
        mBike.cycle();
        mBike.cycle(45.5);
        mBike.cycle("Mountain Bike", 45.5);
        
    }
}

The following is the output of our code.

run:
The Bicycle is cycling.
The Bicycle is cycling at 45.5 kilometers per hour.
The Mountain Bike is cycling 45.5 kilometers per hour.

b. Dynamic polymorphism

Method overriding is dynamic polymorphism. Method overriding allows us to override the methods of a superclass from its subclass.

Example code: The Bicycle class extends the Vehicle class. Both have move() method. By default, the Bicycle inherits the move() method from the parent class Vehicle. However, it also defines its own move() method. Java will override the original method and call move() method from the subclass.

class Vehicle {
    public void move() {
        System.out.println("This vehicle moves by using petrol.");
    }
}
class Bicycle extends Vehicle {
    public void move() {
        System.out.println("This bicycle moves by cycling.");
    }
}

The TestBicycle class creates a new Vehicle object and calls its move() method. Then it also creates a Bicycle object and calls the polymorphic move()  method again.

class TestBicycle {
    public static void main(String[] args) {
        Vehicle mVehicle = new Vehicle();
        mVehicle.move();
        Bicycle mBicycle = new Bicycle();
        mBicycle.move();
    }
}

The following is the output of our code.

run:
This vehicle moves by using petrol.
This bicycle moves by cycling.

Conclusion

Object-Oriented Programming concepts in Java define how to structure a Java problem more efficiently.

Did you like my article? Please share it using these buttons. Thanks!

Was this article helpful?
Donate with PayPal: https://www.paypal.com/donate

Bessy
Eric Murithi Muchenah

Life is beautiful, time is precious. Make the most out of it.