DEV Community

VasDev
VasDev

Posted on

Java OOP, in a Nutshell

This blog is about the implementation and working of various object oriented programming concepts in Java. If you want a quick overview or recap, then this blog is for you!

Firstly, lets quickly understand the core concepts of OOP:

Encapsulation

Definition : The action of enclosing something in or as if in a capsule. (Oxford)

In programming, encapsulation ensures that the user has limited access to the application data, that too via methods defined inside the application.
Everytime, we encapsulate the data, we define getters and setters to retrieve and assign the values of variables that holds the data, respectively.

The encapsulation of variables and methods in java is achieved with the help of access modifiers. Here are a few of them:

  • public : These methods can be accessed from anywhere, from any file.
  • private : These methods can only be accessed from within the class. Useful for encapsulation of data.
  • protected : These methods can be accessed only from within the class and its subclasses. Applies only when inheritence in involved in the program

Now, lets create a simple program, step by step to understand encapsulation!

Step-1: Create a empty public class Person

public class Person {
    // code will go here
}
Enter fullscreen mode Exit fullscreen mode

Step-2: Declare data members name of type string, and age of type int . Make sure the access modifier of these data members should be private as we dont want users to access them directly.

public class Person {
    private String name; // name of the person
    private int age; // age of the person
}
Enter fullscreen mode Exit fullscreen mode

Step-3: Now, we have variables to hold name and age of a person, but since user cant directly access them, we need to define methods to set the values of these variables. These methods are called setters.

// setters

// sets the name of the person
public void setName(String name) { 
    this.name = name;
}

// sets the age of the person
public void setAge(int age) {
    this.age = age;
}
Enter fullscreen mode Exit fullscreen mode

Step-4: After defining setters, we need to define some more methods which will help the users to retrieve the encapsulated data, these methods are called getters.

// getters

// returns the name of the person
public String getName() { 
    return name;
}

// returns the age of the person
public int getAge() {
    return age;
}
Enter fullscreen mode Exit fullscreen mode

You are all set! In just 4 steps, you have implemented encapsulation.

Now, you can create an object of this class in a driver class (Main class) and retrieve/assign the values to the variables without directly accessing them like this :

public class Main {
    public static void main(String[] args) {
        Person person = new Person(); // creating an instance

        // setting person's name and age
        person.setName("Robert");
        person.setAge("29");

        // getting person's name and age
        person.getName();
        person.getAge();
    }
}
Enter fullscreen mode Exit fullscreen mode

Inheritance

Definition : When a class (sub/child class) derives properties (data members) and behaviors (class methods) from another class (super/parent class), enabling code reuse and extension.
To inherit the properties and behaviors of a super class, we use extends keyword in java

Implementing inheritance with an example:

Step-1 : Create a super class Animal with a method eat(), since every animal eats.

// base/super/parent class
class Animal {
    void eat() {
        System.out.println("This animal eats food.");
    }
}
Enter fullscreen mode Exit fullscreen mode

Step-2 : Create a sub class Dog inheriting Animal class with a method bark(), since dog is the animal that barks.

// Derived/sub/child class
class Dog extends Animal {
    void bark() {
        System.out.println("The dog barks.");
    }
}
Enter fullscreen mode Exit fullscreen mode

Step-3 : Create an instance of Dog class in driver class, and call the methods of both classes.

public class Main {
    public static void main(String[] args) {
        Dog myDog = new Dog();
        myDog.eat();  // Inherited method
        myDog.bark(); // Method specific to Dog
    }
}
Enter fullscreen mode Exit fullscreen mode

Congrats, you have successfully implemented simple Inheritance in Java! Similarly, we can implement multilevel, hierarchical and hybrid inheritance also.

Note : Java doesn't explicitly support multiple inheritance, to implement it, we define abstract methods in interface/s.

Polymorphism

The word polymorphism is derived from Greek and means "having multiple forms."
Definition : the ability of a method to operate on different types of objects, allowing for different behaviors based on the object's actual class.
We use method overloading and method overriding to achieve polymorphism in java. Here's the implementation:

Step-1 : Take the above super class Animal and define a method makeSound() in it.

// base class
class Animal {
    void eat() {
        System.out.println("This animal eats food.");
    }

    void makeSound() { // Method to be overridden
        System.out.println("Some sound of the animal");
    }
}
Enter fullscreen mode Exit fullscreen mode

Step-2 : Write another makeSound() but, with parameter sound of type string. (i.e., makeSound( String sound )). This is known as Method Overloading

// base class
class Animal {
    void makeSound() { // Method to be overridden
        System.out.println("Some sound");
    }
    void makeSound(String sound) { // Overloaded method
        System.out.println(sound);
    }
}
Enter fullscreen mode Exit fullscreen mode

Step-3 : Create a derived class Cat, inheriting Animal

// derived class
class Cat extends Animal {
    // method overriding goes here
}
Enter fullscreen mode Exit fullscreen mode

Step-4 : Rewrite the makeSound() method with cat specific sound. This is known as Method Overriding

// Derived class
class Cat extends Animal {
    @Override // just a convention, not necessary to write
    void makeSound() { // Overriding method
        System.out.println("Meow");
    }
}
Enter fullscreen mode Exit fullscreen mode

Step-5 : Create a Cat object in driver class, and run the overridden and overloaded methods.

public class Main {
    public static void main(String[] args) {
        Animal myAnimal = new Cat(); // A Cat object of type Animal
        myAnimal.makeSound(); // Calls overridden method, outputs "Meow"
        myAnimal.makeSound("Growl"); // Calls overloaded method, outputs "Growl"
    }
}
Enter fullscreen mode Exit fullscreen mode

We have implemented polymorphism in just 5 steps!

Abstraction

Definiton : The process of hiding complex implementation details and exposing only the essential features of an object or system.

Abstraction in Java is achieved with the help of :

  • Abstract Classes : A superclass that defines generalized structure without actual implmentation of methods. It is achiever with the help of abstract keyword, used as both, class and method specifier. It can have non-abstract methods as well.
  • Interfaces : An interface is a class blueprint that only includes static and final methods and variables. It can only contains abstract methods

Here's a simple implementation of Abstraction in Java :
Step-1 : Create an abstract superclass Vehicle with an abstract method startEngine().

public abstract class Vehicle {
    public abstract void startEngine();
}
Enter fullscreen mode Exit fullscreen mode

Step-2 : Create its subclass Car and override the startEngine() method with car specific content.

public class Car extends Vehicle {
    @Override
    public void startEngine() {
        System.out.println("Car engine started");
    }
}
Enter fullscreen mode Exit fullscreen mode

Step-3 : Create an interface flyable with method fly().

public interface Flyable {
    void fly();
}
Enter fullscreen mode Exit fullscreen mode

Step-4 : Create another subclass of Vehicle named Airplane that also implements the flyable interface.

public class Airplane extends Vehicle implements Flyable {
    // overriding of methods goes here
}
Enter fullscreen mode Exit fullscreen mode

Step-5 : Override startEngine() and fly() methods with airplane specific content.

public class Airplane extends Vehicle implements Flyable {
    @Override // overriding abstract class method
    public void startEngine() {
        System.out.println("Airplane engine started");
    }

    @Override // overriding interface method
    public void fly() {
        System.out.println("Airplane is flying");
    }
}
Enter fullscreen mode Exit fullscreen mode

Step-6 : Create a Car and a _Airplane_object in driver class, and run the overridden methods.

public class Main {
    public static void main(String[] args) {
        Vehicle car = new Car();
        car.startEngine();  // Output: Car engine started

        Airplane airplane = new Airplane();
        airplane.startEngine();  // Output: Airplane engine started
        airplane.fly();  // Output: Airplane is flying
    }
}
Enter fullscreen mode Exit fullscreen mode

We have successfully implemented Abstraction in Java with the help of Abstract classes and Interfaces!

In this blog, we have explored and successfully implemented all fundamental Object-Oriented Programming (OOP) concepts. From encapsulation and inheritance to polymorphism and abstraction, these concepts are key to building robust and maintainable software solutions. Thanks for reading..!

Top comments (0)