Bird
Raised Fist0

The 4 OOP Pillars with Interview Examples - Encapsulation, Abstraction, Inheritance, Polymorphism

LLDeasyInterview freq: high
Choose your preparation mode4 modes available
๐ŸŽฏ
The 4 OOP Pillars with Interview Examples - Encapsulation, Abstraction, Inheritance, Polymorphism
40 min ยท easy
easy

Design a system that models the 4 core OOP pillars in Java with concrete interview examples. The system should include classes and interfaces demonstrating encapsulation of data, abstraction of behavior, inheritance hierarchies, and polymorphic method calls.

  • Encapsulation requires private fields with public getters/setters controlling access.
  • Abstraction is demonstrated via abstract classes or interfaces with method declarations.
  • Inheritance forms class hierarchies where subclasses extend abstract base classes.
  • Polymorphism allows method overriding and dynamic dispatch at runtime.
  • Java interfaces cannot hold instance state; abstract classes can.
  • Concurrency is not the focus but thread-safe encapsulation is encouraged.
๐Ÿ“‹
Guided Steps
1/5
Step 1
Encapsulation: Define a class with private state and controlled access
Design a Java class that encapsulates a private field and exposes controlled access via public methods.
๐Ÿ’ก Hint
Use private fields and public synchronized getters/setters to protect state in multithreaded contexts.
Use private fields with public synchronized getter and setter methods to ensure atomic access and visibility guarantees via Java's intrinsic locks.
Mid: Recognizes encapsulation by private fields and public methods. Senior: Explains synchronized ensures atomicity and visibility, preventing race conditions on field access.
โš ๏ธCommon Wrong Answer
Using public fields exposes internal state, breaking encapsulation and allowing uncontrolled modifications leading to inconsistent object state.
Step 2
Abstraction: Create an abstract class with abstract methods
Design an abstract Java class that declares abstract methods to be implemented by subclasses.
๐Ÿ’ก Hint
Use abstract class with abstract methods to enforce a contract and share common state or behavior.
abstract class with abstract methods and protected fields to hold shared instance state; interfaces cannot hold instance fields in Java.
Mid: Identifies abstract class usage for abstraction. Senior: Explains why abstract class is chosen over interface due to shared instance state and partial implementation.
โš ๏ธCommon Wrong Answer
Using interface with default methods but requiring shared instance state leads to duplicated fields in subclasses and violates DRY principle.
Step 3
Inheritance: Establish a class hierarchy with base and derived classes
Design a base class and at least two subclasses that inherit and extend behavior.
๐Ÿ’ก Hint
Use inheritance to reuse code and enable polymorphic behavior via method overriding.
Use inheritance with base class defining common fields and methods; subclasses override methods to provide specific behavior.
Mid: Describes inheritance hierarchy. Senior: Explains how Java method overriding enables polymorphism and dynamic dispatch at runtime.
โš ๏ธCommon Wrong Answer
Duplicating code in subclasses instead of inheriting leads to code bloat and violates DRY and Liskov Substitution Principle.
Step 4
Polymorphism: Implement method overriding and dynamic dispatch
Demonstrate polymorphism by overriding a method in subclasses and invoking it via base class reference.
๐Ÿ’ก Hint
Use method overriding and call overridden methods through base class references to achieve runtime polymorphism.
Override methods in subclasses; invoke via base class reference to leverage Java's virtual method dispatch mechanism.
Mid: Recognizes method overriding. Senior: Explains Java virtual method table lookup enables dynamic dispatch at runtime.
โš ๏ธCommon Wrong Answer
Calling subclass methods directly without base class reference loses polymorphic behavior and violates Open/Closed Principle.
Step 5
Combine all pillars in a cohesive design
Design a small Java system combining encapsulation, abstraction, inheritance, and polymorphism with concrete classes and interfaces.
๐Ÿ’ก Hint
Use private fields, abstract classes, inheritance hierarchies, and overridden methods accessed polymorphically.
Combine private fields with synchronized access, abstract classes with shared state, inheritance for code reuse, and polymorphic method calls via base class references.
Mid: Designs classes demonstrating all pillars. Senior: Explains how each Java mechanism enforces the respective OOP pillar and enables extensibility without modification.
โš ๏ธCommon Wrong Answer
Mixing public fields, concrete classes only, and no method overriding leads to poor encapsulation, no abstraction, and no polymorphism.
๐Ÿ”Œ
API Design Challenge
Design a Java API that clearly demonstrates the 4 OOP pillars with concrete examples, including encapsulated classes, abstract classes, inheritance hierarchies, and polymorphic method calls.
  • Use private fields with synchronized accessors to ensure thread safety and encapsulation.
  • Define abstract classes with protected fields and abstract methods to enforce abstraction.
  • Implement subclasses that override methods to demonstrate polymorphism and inheritance.
๐Ÿ“Š
Scoring Rubric
โ–ผ Show
Must Have - 60%
  • Private fields with synchronized accessors for encapsulation
  • abstract class with abstract methods for abstraction
  • Inheritance hierarchy with method overriding
  • Polymorphic method calls via base class references
  • Explanation of why abstract class chosen over interface due to instance state
Good to Have - 30%
  • Use of protected fields in abstract class for shared state
  • Explanation of Java virtual method dispatch mechanism
  • Demonstration of thread-safe encapsulation
  • Clear separation of concerns following SOLID principles
  • Lifecycle ownership explanation of composition vs inheritance
Bonus - 10%
  • Use of final keyword to prevent unwanted subclassing
  • Use of Java annotations like @Override for clarity
  • Explanation of concurrency implications of synchronized methods
  • Discussion of interface default methods vs abstract classes
  • Examples of polymorphism in collections or method parameters
Public mutable fields break encapsulation and cause unpredictable state changes, leading to inconsistent object state.
Using interface to hold instance state leads to duplicated fields in subclasses and violates DRY principle, increasing maintenance overhead.
Duplicating code in subclasses instead of inheritance causes maintenance overhead and violates Liskov Substitution Principle.
Calling subclass methods directly without base class reference loses polymorphic behavior and violates Open/Closed Principle.
Omitting synchronized on mutable field access causes race conditions and visibility bugs, leading to inconsistent state in multithreaded environments.
โœ…
Model Answer
โ–ผ Reveal

The design models the 4 OOP pillars in Java by defining classes with private fields and synchronized accessors for encapsulation; an abstract class with protected fields and abstract methods for abstraction; an inheritance hierarchy with base and derived classes overriding methods; and polymorphic method calls via base class references to enable dynamic dispatch.

  • Use of private fields with synchronized accessors to ensure thread-safe encapsulation.
  • Choosing abstract class over interface to allow shared instance state and partial implementation.
  • Establishing inheritance hierarchy to promote code reuse and specialization.
  • Implementing method overriding and invoking via base class references to leverage Java's virtual method dispatch for polymorphism.
  • Use private fields with synchronized getters/setters to enforce encapsulation and thread safety.
  • abstract class with protected fields and abstract methods to model abstraction with shared state.
  • Inheritance hierarchy with base class and subclasses overriding methods to reuse code and specialize behavior.
  • Polymorphism via method overriding and dynamic dispatch using base class references.
  • Avoid interfaces for shared instance state since Java interfaces cannot hold fields.
  • Use synchronized keyword on accessor methods to prevent race conditions on mutable state.
  • Follow SOLID principles: Single Responsibility via encapsulation, Open/Closed via abstraction and polymorphism.
  • Lifecycle ownership: base class composes shared state, subclasses extend behavior without modifying base.
  • Java virtual method table enables runtime polymorphism, critical for dynamic behavior.
  • Avoid public mutable fields to prevent external uncontrolled state changes.

Practice

(1/5)
1. In designing the Player abstraction for the Snake and Ladder game, should Player be an abstract class or an interface, and why?
easy
A. Player should be an interface because it only defines behavior without state.
B. Player should be an abstract class because it holds common state like current position and provides default methods.
C. Player should be an interface to allow multiple inheritance of behaviors.
D. Player should be an abstract class to enforce implementation of all methods in subclasses.

Solution

  1. Step 1: Analyze state and behavior requirements

    The Player has common state such as current position on the board and methods like move().
  2. Step 2: Choose abstraction type

    An abstract class allows sharing state and default method implementations, which interfaces (pre-Java 8) cannot provide.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Abstract class holds shared state and behavior [check]
Hint: State + default behavior -> abstract class, not interface [check]
Common Mistakes:
2. In a multi-threaded parking lot system, if parkVehicle() is NOT synchronized, which exact sequence causes double-booking of the same spot?
medium
A. Thread 1 parks vehicle, Thread 2 parks vehicle after Thread 1 finishes.
B. Thread 1 checks spot availability -> true, context switch; Thread 2 checks availability -> true; both park simultaneously.
C. Thread 1 parks vehicle, Thread 2 waits for Thread 1 to release lock before parking.
D. Thread 1 and Thread 2 both fail to find a spot and throw exceptions.

Solution

  1. Step 1: Identify the race condition

    Without synchronization, both threads can read spot as available before either marks it occupied.
  2. Step 2: Trace exact interleaving

    Thread 1: isAvailable() -> true, context switch before marking occupied; Thread 2: isAvailable() -> true, both proceed to park, causing double-booking.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Check-then-act gap without synchronization -> double-booking [check]
Hint: Check availability -> context switch -> both park -> double-booking [check]
Common Mistakes:
3. To support ElectricCar needing ChargingSpot in the existing rate limiter design, what is the minimum change that respects extensibility and avoids modifying existing classes?
hard
A. Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, and update SpotCompatibility map externally
B. Modify VehicleType enum and SpotType enum, then add charging logic inside existing Vehicle and Spot classes
C. Create ElectricCar and ChargingSpot classes but modify RateLimiter to handle new types explicitly
D. Add a boolean isElectric flag to Vehicle and Spot classes and handle charging logic with conditionals

Solution

  1. Step 1: Identify extensibility requirements

    Adding ElectricCar and ChargingSpot should avoid modifying existing classes to respect OCP.
  2. Step 2: Evaluate options for minimal change without modifying existing classes

    Modify VehicleType enum and SpotType enum, then add charging logic inside existing Vehicle and Spot classes modifies enums and existing classes, violating OCP. Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, and update SpotCompatibility map externally adds new enum values and classes, updating compatibility externally, preserving existing classes.
  3. Final Answer:

    Option B -> Option B
  4. Quick Check:

    Modifying enums and existing classes violates extensibility [check]
Hint: Add new enums and classes externally, avoid modifying existing classes [check]
Common Mistakes:
4. The system needs to support ElectricCar and ChargingSpot without modifying existing classes. What is the minimum change to the current design to support this?
hard
A. Create a new ElectricCar class and ChargingSpot class, then modify Cart and Order to handle them explicitly.
B. Modify Vehicle class to add isElectric flag and add logic for charging spots inside existing methods.
C. Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, update SpotCompatibility map; no existing class changes.
D. Add a new interface Chargeable and implement it in ElectricCar and ChargingSpot, modifying existing classes to check for it.

Solution

  1. Step 1: Identify extensibility without modifying existing classes

    Adding new enum values and new subclasses allows extension without changing existing class code.
  2. Step 2: Update SpotCompatibility map to include new types

    Updating compatibility map is a configuration change, not a class modification, preserving OCP.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    Enum extension + new subclasses + compatibility map update -> no existing class change [check]
Hint: Extend enums + subclasses + config map -> no class edits [check]
Common Mistakes:
5. You need to add support for ElectricCar and ChargingSpot in the existing parking system using the Iterator pattern. What is the minimum change to the current design to support this without modifying existing classes?
hard
A. Modify Vehicle and Spot classes to include electric-specific fields and logic, then update iterators accordingly.
B. Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, and update SpotCompatibility map; existing classes remain unchanged.
C. Create a new ElectricVehicle interface extending Vehicle and a ChargingSpot class, then modify existing iterators to handle them.
D. Add a flag isElectric to Vehicle class and modify SpotCompatibility to check this flag during iteration.

Solution

  1. Step 1: Identify extensibility requirements

    Adding ElectricCar and ChargingSpot should not require modifying existing classes to respect OCP.
  2. Step 2: Evaluate options

    Add ELECTRIC_CAR to VehicleType enum, CHARGING to SpotType enum, create ElectricCar subclass, and update SpotCompatibility map; existing classes remain unchanged. adds new enums and classes without modifying existing ones, preserving OCP. Modify Vehicle and Spot classes to include electric-specific fields and logic, then update iterators accordingly. modifies existing classes, violating OCP. Create a new ElectricVehicle interface extending Vehicle and a ChargingSpot class, then modify existing iterators to handle them. adds interfaces but requires modifying iterators, violating OCP. Add a flag isElectric to Vehicle class and modify SpotCompatibility to check this flag during iteration. modifies Vehicle class, violating OCP.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Adding new enums and subclasses without changing existing classes respects OCP [check]
Hint: Add new types via enums and subclasses, no existing class changes [check]
Common Mistakes:
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard