Skip to content

Latest commit

 

History

History
962 lines (736 loc) · 20.8 KB

File metadata and controls

962 lines (736 loc) · 20.8 KB

Difference Between a Class and an Object

1. Class:

  • A class is a blueprint or template for creating objects.
  • It defines the structure, behavior, and attributes that objects of the class will have.
  • Classes do not occupy memory until an object is created.

Example: Class Definition

// Defining a class named 'Car'
public class Car {
    // Attributes of the Car class
    String make;
    String model;
    int year;

    // Constructor to initialize Car objects
    public Car(String make, String model, int year) {
        this.make = make;
        this.model = model;
        this.year = year;
    }

    // Method to display car details
    public void displayDetails() {
        System.out.println("Make: " + make);
        System.out.println("Model: " + model);
        System.out.println("Year: " + year);
    }
}

Object

Definition:

  • An object is an instance of a class.
  • Objects are created based on the structure defined in the class and occupy memory.
  • Objects contain actual values for the attributes defined in the class blueprint.

Example: Object Creation

public class Main {
    public static void main(String[] args) {
        // Creating an object of the Car class
        Car myCar = new Car("Toyota", "Corolla", 2020);

        // Accessing the object's methods and attributes
        myCar.displayDetails();  // This will print the car's details
    }
}

Key Differences Between Class and Object

Aspect Class Object
Definition Blueprint or template for creating objects. Instance of a class.
Memory Usage Does not occupy memory. Occupies memory when created.
Behavior Defines behavior through methods. Exhibits behavior defined by the class.
State Does not have a state. Has a state (attribute values).
Example Car (defined as a class). myCar (an instance of the Car class).

What is Polymorphism?

Polymorphism in Object-Oriented Programming (OOP) refers to the ability of a single interface to represent different types or forms. It allows objects to be treated as instances of their parent class, enabling flexibility and reuse.

There are two types of polymorphism in Java:

  1. Compile-Time Polymorphism (Static Binding)
  2. Runtime Polymorphism (Dynamic Binding)

1. Compile-Time Polymorphism

Compile-time polymorphism occurs when a method is resolved during compile time. This is achieved using method overloading.

Example: Method Overloading

class Calculator {
    int add(int a, int b) {
        return a + b;
    }

    int add(int a, int b, int c) {
        return a + b + c;
    }
}

public class Main {
    public static void main(String[] args) {
        Calculator calc = new Calculator();
        System.out.println(calc.add(5, 10));        // Output: 15
        System.out.println(calc.add(5, 10, 20));   // Output: 35
    }
}

2. Runtime Polymorphism

Runtime polymorphism occurs when a method is resolved during runtime. This is achieved using method overriding.

Example: Method Overriding

class Animal {
    void sound() {
        System.out.println("Animal makes a sound");
    }
}

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

public class Main {
    public static void main(String[] args) {
        Animal myAnimal = new Dog();  // Upcasting
        myAnimal.sound();             // Output: Dog barks
    }
}

Key Differences

Feature Compile-Time Polymorphism Runtime Polymorphism
Binding Time Compile time Runtime
Achieved By Method Overloading Method Overriding
Flexibility Limited High

What is Encapsulation?

Encapsulation is one of the fundamental principles of Object-Oriented Programming (OOP). It refers to bundling data (variables) and methods (functions) that operate on the data into a single unit, typically a class. Encapsulation helps protect the internal state of an object and ensures controlled access through methods.


Key Benefits of Encapsulation

  1. Data Hiding: Restricts direct access to some of an object’s components.
  2. Controlled Access: Provides public methods (getters and setters) for controlled interaction with the internal data.
  3. Modularity: Improves code maintainability by separating concerns.
  4. Security: Prevents unintended interference and misuse of the object's state.

How is Encapsulation Achieved in Java?

In Java, encapsulation is achieved by:

  1. Declaring Class Variables as Private: Ensures that the internal state is hidden from external access.
  2. Providing Public Getters and Setters: Allows controlled access and modification of private variables.

Example: Encapsulation in Java

class Employee {
    // Private variables (data hiding)
    private String name;
    private double salary;

    // Constructor to initialize values
    public Employee(String name, double salary) {
        this.name = name;
        this.salary = salary;
    }

    // Public getter for name
    public String getName() {
        return name;
    }

    // Public setter for name
    public void setName(String name) {
        this.name = name;
    }

    // Public getter for salary
    public double getSalary() {
        return salary;
    }

    // Public setter for salary
    public void setSalary(double salary) {
        if (salary > 0) {  // Adding validation
            this.salary = salary;
        } else {
            System.out.println("Invalid salary amount.");
        }
    }
}

public class Main {
    public static void main(String[] args) {
        // Creating an instance of Employee
        Employee emp = new Employee("John Doe", 50000);

        // Accessing and modifying private variables using getters and setters
        System.out.println("Name: " + emp.getName());
        System.out.println("Salary: " + emp.getSalary());

        // Modifying the salary
        emp.setSalary(60000);
        System.out.println("Updated Salary: " + emp.getSalary());

        // Trying to set an invalid salary
        emp.setSalary(-10000);  // Output: Invalid salary amount.
    }
}

Summary

Encapsulation is a powerful concept in OOP that:

  • Protects the internal state of an object.
  • Provides a controlled interface for interaction.
  • Ensures modularity, security, and maintainability in the code.

4. What are Access Modifiers?

Access modifiers in Java define the visibility or accessibility of a class, method, or variable.

Types of Access Modifiers

  1. public: Accessible from anywhere.
  2. private: Accessible only within the defining class.
  3. protected: Accessible within the same package and by subclasses in other packages.
  4. default (package-private): Accessible only within the same package.

Example

class Example {
    public int publicVar = 10;      // Accessible everywhere
    private int privateVar = 20;    // Accessible only within this class
    protected int protectedVar = 30; // Accessible within package and subclasses
    int defaultVar = 40;           // Accessible within the same package
}

5. What is Abstraction?

Abstraction hides the implementation details and only shows the essential features of an object.

Abstract Classes vs Interfaces

Feature Abstract Class Interface
Methods Can have abstract and concrete methods All methods are abstract by default (before Java 8).
Variables Can have instance variables Only constants (static final).
Inheritance A class can extend only one abstract class A class can implement multiple interfaces.

Example: Abstract Class

abstract class Animal {
    abstract void sound();
    void sleep() {
        System.out.println("Sleeping...");
    }
}

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

Example: Interface

interface Shape {
    void draw();
}

interface Color {
    void fill();
}

class Circle implements Shape, Color {
    @Override
    public void draw() {
        System.out.println("Drawing a circle");
    }

    @Override
    public void fill() {
        System.out.println("Filling with color");
    }
}

6. Interface vs Abstract Class

When to Use Abstract Class Over Interface?

Use an abstract class when:

  • You need to share code among multiple related classes.
  • You want to define non-static or non-final fields.

7. Inheritance vs Composition

Difference

Aspect Inheritance Composition
Relationship "is-a" relationship "has-a" relationship
Flexibility Rigid Flexible

Why Composition is Better?

  • Promotes reusability.
  • Reduces coupling.

8. What is Multiple Inheritance?

Multiple inheritance allows a class to inherit from multiple classes.

Python Example

class A:
    def method_a(self):
        print("Method from A")

class B:
    def method_b(self):
        print("Method from B")

class C(A, B):
    pass

obj = C()
obj.method_a()
obj.method_b()

Why Not Supported in Java?

To avoid ambiguity caused by the Diamond Problem.


9. What is the this Keyword?

The this keyword refers to the current object.

Example

class Example {
    int value;

    Example(int value) {
        this.value = value;  // Refers to the instance variable
    }

    void display() {
        System.out.println("Value: " + this.value);
    }
}

10. What is Method Overriding?

Method overriding occurs when a subclass provides a specific implementation of a method defined in its parent class.

Rules

  1. Method must have the same name and parameters.
  2. Method in the subclass must have the same or narrower access level.
  3. The return type must be the same or covariant.

Example

class Parent {
    void display() {
        System.out.println("Display from Parent");
    }
}

class Child extends Parent {
    @Override
    void display() {
        System.out.println("Display from Child");
    }
}

public class Main {
    public static void main(String[] args) {
        Parent obj = new Child();  // Upcasting
        obj.display();             // Output: Display from Child
    }
}

Advanced OOP Concepts

11. Static Methods and Static Variables

What are Static Methods and Variables?

  • Static Methods: Methods belonging to the class rather than any specific object. They can be accessed without creating an instance.
  • Static Variables: Variables shared among all instances of a class.

When to Use Them?

  • For utility or helper methods (e.g., Math.sqrt()).
  • To share common data across all objects.

Limitations

  • Static methods cannot access instance variables/methods directly.
  • Static methods cannot be overridden.

Example

class Example {
    static int counter = 0; // Static variable

    static void incrementCounter() { // Static method
        counter++;
    }
}

12. Constructors

What is a Constructor?

A constructor is a special method used to initialize objects.

Copy Constructor vs Default Constructor

  • Default Constructor: A no-argument constructor provided by Java or defined by the programmer.
  • Copy Constructor: Creates a new object by copying an existing object.

Example

class Example {
    int value;

    // Default constructor
    Example() {
        value = 0;
    }

    // Copy constructor
    Example(Example obj) {
        this.value = obj.value;
    }
}

13. Deep Copy vs Shallow Copy

Difference

  • Shallow Copy: Copies the references, not the actual objects.
  • Deep Copy: Creates a new object for each field.

Example

import java.util.ArrayList;

class Example implements Cloneable {
    ArrayList list;

    Example() {
        list = new ArrayList<>();
    }

    // Shallow Copy
    Example shallowCopy() {
        return this;
    }

    // Deep Copy
    Example deepCopy() {
        Example copy = new Example();
        copy.list.addAll(this.list);
        return copy;
    }
}

14. Final Classes and Methods in Java

Final Classes

  • A final class cannot be extended.
  • Used to prevent inheritance.

Final Methods

  • Cannot be overridden in subclasses.

Example

final class Example {
    final void display() {
        System.out.println("Final Method");
    }
}

15. == vs .equals()

Difference

  • == compares memory addresses.
  • .equals() compares the content of objects.

Example

String str1 = "Hello";
String str2 = new String("Hello");

System.out.println(str1 == str2);       // false
System.out.println(str1.equals(str2)); // true

16. Garbage Collection in Java

Purpose

Reclaims memory occupied by unreferenced objects.

How It Works

  • JVM automatically calls garbage collection.
  • Can be explicitly requested using System.gc().

17. Dynamic Method Dispatch

What is It?

Dynamic Method Dispatch allows method resolution at runtime (runtime polymorphism).

Example

class Parent {
    void display() {
        System.out.println("Parent Display");
    }
}

class Child extends Parent {
    @Override
    void display() {
        System.out.println("Child Display");
    }
}

public class Main {
    public static void main(String[] args) {
        Parent obj = new Child();
        obj.display(); // Output: Child Display
    }
}

18. super Keyword

Usage

  • Access parent class methods/constructors.
  • Reference parent class variables.

Example

class Parent {
    Parent() {
        System.out.println("Parent Constructor");
    }
}

class Child extends Parent {
    Child() {
        super(); // Calls parent constructor
        System.out.println("Child Constructor");
    }
}

19. Dependency Injection (DI)

What is DI?

A design pattern to achieve loose coupling by injecting dependencies from the outside.

Example

interface Service {
    void execute();
}

class MyService implements Service {
    public void execute() {
        System.out.println("Executing Service");
    }
}

class Client {
    private Service service;

    Client(Service service) {
        this.service = service; // Dependency Injection
    }

    void doWork() {
        service.execute();
    }
}

20. Aggregation vs Composition

Difference

Aspect Aggregation Composition
Relationship "Has-a" relationship Strong "Part-of" relationship
Lifespan Independent lifespan Dependent lifespan

Example: Aggregation

class Address {
    String city;
}

class Person {
    Address address;
}

Example: Composition

class Engine {
    void start() {
        System.out.println("Engine Starting...");
    }
}

class Car {
    private final Engine engine = new Engine();
    void startCar() {
        engine.start();
    }
}

Design-Oriented Questions

21. Transportation System Class Hierarchy

Class Hierarchy

class Vehicle {
    void start() {
        System.out.println("Vehicle started");
    }

    void stop() {
        System.out.println("Vehicle stopped");
    }
}

class Car extends Vehicle {
    void airConditioning() {
        System.out.println("Car AC turned on");
    }
}

class Bike extends Vehicle {
    void kickStart() {
        System.out.println("Bike kick-started");
    }
}

class Truck extends Vehicle {
    void loadCargo() {
        System.out.println("Truck loaded with cargo");
    }
}

22. ATM System Design

Class Diagram

  1. Account: Contains balance, deposit(), withdraw().
  2. Customer: Has Account.
  3. Bank: Manages multiple Customers.
  4. Transaction: Logs transaction details.

Code

class Account {
    private double balance;

    void deposit(double amount) {
        balance += amount;
    }

    void withdraw(double amount) {
        if (balance >= amount) balance -= amount;
    }
}

class Customer {
    private Account account;

    Customer(Account account) {
        this.account = account;
    }
}

class Bank {
    private List customers;
}

23. E-Commerce System

Classes and Relationships

  • Product: Represents items.
  • User: Customer of the platform.
  • Cart: Aggregates Products.
  • Order: Composed of Cart.

Code

class Product {
    String name;
    double price;
}

class User {
    String username;
}

class Cart {
    private List products;
}

class Order {
    private Cart cart;
}

24. Singleton Pattern

Code

class Singleton {
    private static Singleton instance;

    private Singleton() {}

    public static synchronized Singleton getInstance() {
        if (instance == null) {
            instance = new Singleton();
        }
        return instance;
    }
}

25. Factory Design Pattern

Example: Shape Factory

interface Shape {
    void draw();
}

class Circle implements Shape {
    public void draw() {
        System.out.println("Drawing Circle");
    }
}

class Square implements Shape {
    public void draw() {
        System.out.println("Drawing Square");
    }
}

class ShapeFactory {
    static Shape createShape(String type) {
        if (type.equals("Circle")) return new Circle();
        else if (type.equals("Square")) return new Square();
        return null;
    }
}

26. Observer Pattern

Example: NewsPublisher

interface Subscriber {
    void update(String news);
}

class NewsPublisher {
    private List subscribers = new ArrayList<>();

    void addSubscriber(Subscriber sub) {
        subscribers.add(sub);
    }

    void notifySubscribers(String news) {
        for (Subscriber sub : subscribers) sub.update(news);
    }
}

27. Zoo Management System

Classes

  • Animal: Base class with makeSound().
  • Mammal, Bird: Inherit Animal.
  • ZooKeeper: Feeds animals.

Code

class Animal {
    void makeSound() {
        System.out.println("Animal sound");
    }
}

class Mammal extends Animal {}

class ZooKeeper {
    void feedAnimal(Animal animal) {
        System.out.println("Feeding animal");
    }
}

28. Builder Pattern

Example: Car Builder

class Car {
    private String color;
    private boolean hasSunroof;

    static class Builder {
        private String color;
        private boolean hasSunroof;

        Builder setColor(String color) {
            this.color = color;
            return this;
        }

        Builder setSunroof(boolean sunroof) {
            this.hasSunroof = sunroof;
            return this;
        }

        Car build() {
            return new Car(this);
        }
    }

    private Car(Builder builder) {
        this.color = builder.color;
        this.hasSunroof = builder.hasSunroof;
    }
}

29. Parking Lot System

Classes

  • ParkingSpot: Represents spots.
  • Vehicle: Car, Bike, Truck.
  • ParkingLot: Manages ParkingSpots.

Code

class ParkingSpot {
    boolean isOccupied;
}

class Vehicle {
    String plateNumber;
}

class ParkingLot {
    private List spots;
}

30. Scalable Notification System

Components

  1. Notification: Abstract class with send().
  2. EmailNotification, SMSNotification: Extend Notification.
  3. NotificationService: Sends notifications.

Code

abstract class Notification {
    abstract void send(String message);
}

class EmailNotification extends Notification {
    void send(String message) {
        System.out.println("Email sent: " + message);
    }
}

class SMSNotification extends Notification {
    void send(String message) {
        System.out.println("SMS sent: " + message);
    }
}

class NotificationService {
    void notifyUser(Notification notification, String message) {
        notification.send(message);
    }
}