Company Wise Interview Questions And Answers
About Lesson

Let me break down the key Object-Oriented Programming (OOP) concepts in a way that’s easy to relate to.


1. Inheritance

Inheritance is like when you inherit traits from your parents, but in OOP, it’s about one class getting properties and behaviors from another class. Inheritance helps avoid code duplication by allowing you to reuse code from a parent class in child classes.

Example:

Let’s say you have a Vehicle class, and you want to create different types of vehicles like Car and Bike. Instead of rewriting the same properties (like color or speed) in both classes, you can just inherit from the Vehicle class.


class Vehicle {
    String color;
    int speed;

    public Vehicle(String color, int speed) {
        this.color = color;
        this.speed = speed;
    }

    public void start() {
        System.out.println("Vehicle is starting.");
    }
}

class Car extends Vehicle {
    int wheels;

    public Car(String color, int speed, int wheels) {
        super(color, speed);  // Calling the parent class constructor
        this.wheels = wheels;
    }

    public void honk() {
        System.out.println("Car is honking.");
    }
}

class Bike extends Vehicle {
    boolean hasPedals;

    public Bike(String color, int speed, boolean hasPedals) {
        super(color, speed);
        this.hasPedals = hasPedals;
    }

    public void ringBell() {
        System.out.println("Bike bell is ringing.");
    }
}

 

In this example:

  • Car and Bike both inherit the properties (color, speed) and methods (start()) from Vehicle.
  • They also have their own specific methods, like honk() and ringBell().

Key Takeaway: Inheritance helps you build on existing code rather than duplicating it, making your code more organized and reusable.

 


2. Polymorphism

Polymorphism means “many forms”. In OOP, it allows objects of different classes to be treated as objects of a common superclass, particularly useful when you want to call the same method on objects of different types. The actual method that gets called depends on the type of object that is invoking it.

 

There are two types of polymorphism:

  • Compile-time polymorphism (Method Overloading)
  • Runtime polymorphism (Method Overriding)

 

Example of Runtime Polymorphism (Method Overriding):

In this example, both Car and Bike can have their own version of a method like start() from the Vehicle class. This is where method overriding happens.

 


class Vehicle {
    public void start() {
        System.out.println("Vehicle is starting.");
    }
}

class Car extends Vehicle {
    @Override
    public void start() {
        System.out.println("Car is starting with a roar.");
    }
}

class Bike extends Vehicle {
    @Override
    public void start() {
        System.out.println("Bike is starting quietly.");
    }
}

 

Output:

Car is starting with a roar.
Bike is starting quietly.

This is polymorphism in action—one method (start()) behaving differently based on the type of object it is called on.

Key Takeaway: Polymorphism allows you to write more flexible code. You don’t need to know exactly which subclass you’re working with—you just know that it’s a subclass of a common parent (like Vehicle) and will behave in a certain way (override its methods).

 


3. Encapsulation

Encapsulation is the idea of bundling the data (variables) and the methods that operate on the data into a single unit (class). It also means controlling access to this data by using access modifiers (e.g., private, public) to hide the internal details and expose only what’s necessary.

Example:


class Person {
    private String name;  // cannot be accessed directly outside this class
    private int age;      // cannot be accessed directly

    public String getName() {  // Getter method to access name
        return name;
    }

    public void setName(String name) {  // Setter method to modify name
        this.name = name;
    }

    public int getAge() {  // Getter method to access age
        return age;
    }

    public void setAge(int age) {  // Setter method to modify age
        if (age > 0) {  // Adding validation to ensure age is positive
            this.age = age;
        }
    }
}

With encapsulation, you can control how the name and age are set and accessed, instead of exposing them directly. The Person class hides the actual data and provides getter and setter methods to access and modify the values.

Key Takeaway: Encapsulation keeps data safe from outside interference and misuse by protecting it behind methods. It also allows you to control how data is accessed and modified, which is helpful for validation or logging.

 


4. Abstraction

Abstraction is about hiding the complex implementation and showing only the essential details. It helps simplify the interaction with complex systems by providing a clear interface to the user. Think of it as using a TV remote: you don’t need to know how the TV works internally; you just press buttons to change channels.

Example:


abstract class Animal {
    public abstract void sound();  // Abstract method, needs to be implemented by subclasses
}

class Dog extends Animal {
    @Override
    public void sound() {
        System.out.println("Woof! Woof!");
    }
}

class Cat extends Animal {
    @Override
    public void sound() {
        System.out.println("Meow! Meow!");
    }
}

 

In this example, Animal is an abstract class with an abstract method sound(). The Dog and Cat classes must implement the sound() method, but the user of the Animal class doesn’t need to know the specifics of how each animal makes its sound—they can just call sound() and get the correct behavior.

Key Takeaway: Abstraction hides complex implementation details and only exposes what’s necessary. It makes the code more understandable and easier to work with.