Most Asked Infosys Object-Oriented Programming (OOPs) Interview Questions

Mastering Object-Oriented Programming (OOP) Principles: A Comprehensive Guide

Mastering Object-Oriented Programming (OOP) Principles: A Comprehensive Guide

Object-Oriented Programming (OOP) is a fundamental programming paradigm that structures code around "objects" rather than actions and data. It's the backbone of countless applications, providing a powerful way to model real-world entities and their interactions. This guide will delve into the core principles of OOP, equipping you with a solid understanding of its concepts and applications.

What are the four main principles of OOP?

The four main principles of OOP are Abstraction, Encapsulation, Inheritance, and Polymorphism. These principles work together to create modular, reusable, and maintainable code. Let's briefly define each:

  • Abstraction: Simplifying complex systems by modeling only essential details and hiding unnecessary complexity.
  • Encapsulation: Bundling data and methods that operate on that data within a single unit (a class), protecting the data from unauthorized access.
  • Inheritance: Creating new classes (child classes) based on existing classes (parent classes), inheriting their properties and behaviors. This promotes code reusability.
  • Polymorphism: The ability of objects of different classes to respond to the same method call in their own specific way. This allows for flexible and extensible code.

Explain abstraction with a real-life example.

Abstraction is about hiding complex implementation details and showing only essential information. A great real-life example is driving a car. You interact with the steering wheel, gas pedal, and brakes, but you don't need to understand the intricate workings of the engine, transmission, or braking system to drive. The car's controls provide an abstract interface to its complex internal mechanisms. Similarly, in programming, a class might represent a "car" object, exposing methods like start(), accelerate(), and brake() without revealing the internal implementation of these actions.

What is encapsulation and how is it implemented?

Encapsulation is the bundling of data (attributes) and methods (functions) that operate on that data within a class, protecting the data from direct access. This is achieved through access modifiers: public, private, and protected. private members are only accessible within the class itself, protected members are accessible within the class and its subclasses, and public members are accessible from anywhere. Using getters and setters (accessor and mutator methods) allows controlled access to private data, ensuring data integrity and preventing unintended modifications. For example, a BankAccount class might have a private balance variable with public getter (getBalance()) and setter (deposit(), withdraw()) methods to manage the balance.

Difference between method overloading and method overriding.

Both method overloading and overriding are forms of polymorphism, but they differ in their implementation and context.

  • Method Overloading: Occurs within the same class. Multiple methods have the same name but different parameters (number, type, or order). The compiler determines which method to call at compile time based on the arguments provided (compile-time polymorphism).
  • Method Overriding: Occurs in inheritance. A subclass provides a specific implementation for a method that is already defined in its superclass. The method called is determined at runtime (runtime polymorphism) based on the object's type.

Example (Java):


//Overloading
class MyClass {
    void myMethod(int x) { ... }
    void myMethod(String s) { ... }
}

//Overriding
class Animal {
    void makeSound() { System.out.println("Generic animal sound"); }
}
class Dog extends Animal {
    @Override
    void makeSound() { System.out.println("Woof!"); }
}
    

Difference between abstract class and interface in Java.

Both abstract classes and interfaces are used to define blueprints for classes, but they have key differences:

  • Abstract Class: Can have both abstract (no implementation) and concrete (with implementation) methods. Can have instance variables. A class can extend only one abstract class.
  • Interface: Before Java 8, only had abstract methods. Since Java 8, can have default and static methods. Can't have instance variables (except static constants). A class can implement multiple interfaces.

What is multiple inheritance? Why is it not allowed in Java?

Multiple inheritance allows a class to inherit from multiple parent classes. This can lead to the "diamond problem," where a class inherits from two classes that have a common ancestor, resulting in ambiguity if the common ancestor has methods with the same signature. Java doesn't support multiple inheritance of classes directly to avoid this ambiguity and enhance code maintainability. Java achieves similar functionality through interfaces, which allow a class to implement multiple interfaces without the ambiguity of multiple inheritance.

What is a virtual function and pure virtual function in C++?

Virtual functions and pure virtual functions are crucial concepts in C++ for achieving runtime polymorphism.

  • Virtual Function: A member function declared using the virtual keyword. When a virtual function is called through a base-class pointer or reference, the correct version for the actual object type is executed at runtime (dynamic dispatch). This allows for flexible extensibility.
  • Pure Virtual Function: A virtual function declared as virtual void myFunction() = 0;. A class containing a pure virtual function is an abstract class. Abstract classes cannot be instantiated; they serve as blueprints for derived classes that provide implementations for the pure virtual functions. Pure virtual functions define an interface that derived classes must implement.

Difference between deep copy and shallow copy.

Shallow copy and deep copy refer to different ways of duplicating objects.

  • Shallow Copy: Creates a new object but populates it with references to the same data as the original object. If the original object contains references to other objects, the copy will point to those same objects. Changes to those referenced objects in either the original or the copy will affect both.
  • Deep Copy: Creates a completely independent copy of the object, including any nested objects. Changes to the original object will not affect the copy, and vice-versa.

What is the diamond problem in C++?

The diamond problem arises in C++ when a class inherits from two classes that share a common ancestor, and all three classes define the same method. If the derived class tries to call this method, the compiler is unclear which version to use (the one from the common ancestor or one of the inherited classes). This ambiguity can lead to unpredictable behavior and errors. This is a classic example of why multiple inheritance can be problematic.

Can constructors be virtual in C++? Why or why not?

No, constructors cannot be virtual in C++. Virtual functions rely on the existence of a virtual table (vtable) that is built during object construction. A virtual constructor would create a circular dependency: you would need the vtable to create the object, but the vtable can only be created after the object is constructed.

What is the use of this pointer in C++?

The this pointer is a hidden pointer passed implicitly to all non-static member functions in C++. It points to the current object instance on which the member function is being called. It allows a method to access and modify the object's members. It is particularly useful when working with member variables that have the same name as parameters passed to the method, allowing to distinguish between the two.


class MyClass {
public:
    void setX(int x) {
        this->x = x; // 'this->x' refers to the member variable
    }
private:
    int x;
};
    

Conclusion: Mastering Object-Oriented Programming principles is essential for building robust, scalable, and maintainable software. By understanding abstraction, encapsulation, inheritance, and polymorphism, developers can create modular and reusable code that effectively models real-world entities and their interactions. Continuous practice and exploration will solidify your grasp of these core concepts.