Skip to main content
OOP Fundamentals
  1. Resources/
  2. Study Materials/
  3. Information & Communication Technology Engineering/
  4. ICT Semester 4/
  5. Java Programming (4343203)/
  6. Java Programming Slidev Presentations/

OOP Fundamentals

·
Milav Dabgar
Author
Milav Dabgar
Experienced lecturer in the electrical and electronic manufacturing industry. Skilled in Embedded Systems, Image Processing, Data Science, MATLAB, Python, STM32. Strong education professional with a Master’s degree in Communication Systems Engineering from L.D. College of Engineering - Ahmedabad.
Table of Contents

OOP Fundamentals
#

Lecture 10
#

Java Programming (4343203)
Diploma in ICT - Semester IV
Gujarat Technological University

Press Space for next page

layout: default
#

Learning Objectives
#

By the end of this lecture, you will be able to:

  • ๐ŸŽฏ Understand the core principles of Object-Oriented Programming
  • ๐Ÿ—๏ธ Explain the concept of classes and objects
  • ๐Ÿ”’ Apply encapsulation principles in Java programs
  • ๐ŸŽญ Recognize polymorphism in different forms
  • ๐Ÿ“ Implement abstraction using classes and methods
  • ๐Ÿงฌ Understand inheritance relationships between classes
  • ๐Ÿ› ๏ธ Create simple classes demonstrating OOP concepts

layout: default
#

What is Object-Oriented Programming?
#

Definition
#

Object-Oriented Programming (OOP) is a programming paradigm that organizes software design around objects rather than functions and logic.

Real-World Analogy
#

Think of OOP like describing real-world entities:

  • Car is a class (blueprint)
  • Your specific car is an object (instance)
  • Properties: color, model, speed, fuel
  • Actions: start(), stop(), accelerate(), brake()

Key Characteristics
#

  • Modularity: Code organized in discrete objects
  • Reusability: Objects can be reused in different programs
  • Maintainability: Easier to modify and debug
  • Scalability: Easy to add new features
  • Real-world modeling: Mirrors how we think about problems

OOP vs Procedural Programming
#

Procedural Approach
#

// Traditional procedural style
public class CalculatorProcedural {
    public static void main(String[] args) {
        // All logic in main method
        double num1 = 10;
        double num2 = 5;
        
        double sum = num1 + num2;
        double difference = num1 - num2;
        double product = num1 * num2;
        double quotient = num1 / num2;
        
        System.out.println("Sum: " + sum);
        System.out.println("Difference: " + difference);
        System.out.println("Product: " + product);
        System.out.println("Quotient: " + quotient);
    }
}

Object-Oriented Approach
#

// Object-oriented style
public class Calculator {
    private double num1, num2;
    
    public Calculator(double num1, double num2) {
        this.num1 = num1;
        this.num2 = num2;
    }
    
    public double add() { return num1 + num2; }
    public double subtract() { return num1 - num2; }
    public double multiply() { return num1 * num2; }
    public double divide() { return num1 / num2; }
    
    public void displayResults() {
        System.out.println("Sum: " + add());
        System.out.println("Difference: " + subtract());
        System.out.println("Product: " + multiply());
        System.out.println("Quotient: " + divide());
    }
}

layout: default
#

Classes and Objects
#

What is a Class?
#

A class is a blueprint or template for creating objects. It defines:

  • Attributes (data/properties)
  • Methods (behavior/actions)

What is an Object?
#

An object is an instance of a class. It has:

  • State (actual values of attributes)
  • Behavior (methods that can be called)

Class Definition Syntax
#

public class ClassName {
    // Attributes (fields/variables)
    dataType attribute1;
    dataType attribute2;
    
    // Constructor
    public ClassName(parameters) {
        // Initialize attributes
    }
    
    // Methods
    public returnType methodName(parameters) {
        // Method body
        return value;
    }
}

Real-World Example: Student Class
#

public class Student {
    // Attributes
    private String name;
    private int rollNumber;
    private double marks;
    
    // Constructor
    public Student(String name, int rollNumber, double marks) {
        this.name = name;
        this.rollNumber = rollNumber;
        this.marks = marks;
    }
    
    // Methods
    public void displayInfo() {
        System.out.println("Name: " + name);
        System.out.println("Roll Number: " + rollNumber);
        System.out.println("Marks: " + marks);
    }
    
    public char getGrade() {
        if (marks >= 90) return 'A';
        else if (marks >= 80) return 'B';
        else if (marks >= 70) return 'C';
        else if (marks >= 60) return 'D';
        else return 'F';
    }
}

Object Creation and Usage
#

public class StudentDemo {
    public static void main(String[] args) {
        // Creating objects (instances)
        Student student1 = new Student("John Doe", 101, 85.5);
        Student student2 = new Student("Jane Smith", 102, 92.0);
        Student student3 = new Student("Bob Johnson", 103, 78.0);
        
        // Using objects
        System.out.println("=== Student 1 ===");
        student1.displayInfo();
        System.out.println("Grade: " + student1.getGrade());
        
        System.out.println("\n=== Student 2 ===");
        student2.displayInfo();
        System.out.println("Grade: " + student2.getGrade());
        
        System.out.println("\n=== Student 3 ===");
        student3.displayInfo();
        System.out.println("Grade: " + student3.getGrade());
    }
}

Memory Representation
#

// When you create objects:
Student student1 = new Student("John", 101, 85.5);
Student student2 = new Student("Jane", 102, 92.0);

/*
Memory Layout:
+-----------+     +------------------+
| student1  |---->| name: "John"     |
+-----------+     | rollNumber: 101  |
                  | marks: 85.5      |
                  +------------------+

+-----------+     +------------------+
| student2  |---->| name: "Jane"     |
+-----------+     | rollNumber: 102  |
                  | marks: 92.0      |
                  +------------------+
*/

Key Points
#

  • One class, many objects: Multiple objects can be created from one class
  • Independent state: Each object has its own copy of attributes
  • Shared behavior: All objects share the same methods
  • Memory efficiency: Methods are stored once, shared by all objects

layout: default
#

The Four Pillars of OOP
#

1. Encapsulation ๐Ÿ”’
#

Definition: Bundling data and methods together, hiding internal details.

Benefits:
#

  • Data Protection: Prevent unauthorized access
  • Controlled Access: Use getters and setters
  • Code Maintenance: Changes don’t affect other code
  • Validation: Ensure data integrity

Example: Bank Account
#

public class BankAccount {
    private double balance;  // Private - hidden from outside
    private String accountNumber;
    
    public BankAccount(String accountNumber, double initialBalance) {
        this.accountNumber = accountNumber;
        if (initialBalance >= 0) {
            this.balance = initialBalance;
        } else {
            this.balance = 0;
        }
    }
    
    // Controlled access through methods
    public double getBalance() {
        return balance;
    }
    
    public void deposit(double amount) {
        if (amount > 0) {
            balance += amount;
            System.out.println("Deposited: $" + amount);
        } else {
            System.out.println("Invalid deposit amount");
        }
    }
    
    public void withdraw(double amount) {
        if (amount > 0 && amount <= balance) {
            balance -= amount;
            System.out.println("Withdrawn: $" + amount);
        } else {
            System.out.println("Invalid withdrawal amount");
        }
    }
}

2. Inheritance ๐Ÿงฌ
#

Definition: Creating new classes based on existing classes.

Benefits:
#

  • Code Reusability: Reuse existing code
  • Hierarchical Organization: Natural classification
  • Extensibility: Add new features to existing classes
  • Polymorphism Support: Foundation for polymorphic behavior

Example: Vehicle Hierarchy
#

// Parent class (Base class)
public class Vehicle {
    protected String brand;
    protected int speed;
    
    public Vehicle(String brand) {
        this.brand = brand;
        this.speed = 0;
    }
    
    public void start() {
        System.out.println(brand + " vehicle started");
    }
    
    public void accelerate(int increment) {
        speed += increment;
        System.out.println("Speed increased to: " + speed);
    }
}

// Child class (Derived class)
public class Car extends Vehicle {
    private int numberOfDoors;
    
    public Car(String brand, int doors) {
        super(brand);  // Call parent constructor
        this.numberOfDoors = doors;
    }
    
    // New method specific to Car
    public void honk() {
        System.out.println(brand + " car is honking!");
    }
    
    // Override parent method for specific behavior
    @Override
    public void start() {
        System.out.println(brand + " car engine started");
    }
}

// Usage
public class VehicleDemo {
    public static void main(String[] args) {
        Car myCar = new Car("Toyota", 4);
        myCar.start();        // Calls overridden method
        myCar.accelerate(50); // Inherited from Vehicle
        myCar.honk();         // Car-specific method
    }
}

Inheritance Types:
#

  • Single: One parent, one child
  • Multilevel: Chain of inheritance
  • Hierarchical: Multiple children from one parent
  • Multiple: Not directly supported in Java (use interfaces)

layout: default
#

Polymorphism and Abstraction
#

3. Polymorphism ๐ŸŽญ
#

Definition: “Many forms” - same interface, different implementations.

Types of Polymorphism:
#

A. Compile-time Polymorphism (Method Overloading)
#

public class Calculator {
    // Same method name, different parameters
    public int add(int a, int b) {
        return a + b;
    }
    
    public double add(double a, double b) {
        return a + b;
    }
    
    public int add(int a, int b, int c) {
        return a + b + c;
    }
    
    public String add(String a, String b) {
        return a + b;
    }
}

// Usage
Calculator calc = new Calculator();
System.out.println(calc.add(5, 3));        // Calls int version
System.out.println(calc.add(5.5, 3.2));    // Calls double version  
System.out.println(calc.add(1, 2, 3));     // Calls three-parameter version
System.out.println(calc.add("Hello", "World")); // Calls String version

B. Runtime Polymorphism (Method Overriding)
#

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

// Derived classes
public class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Dog barks: Woof!");
    }
}

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

// Polymorphic behavior
public class AnimalDemo {
    public static void main(String[] args) {
        Animal[] animals = {
            new Dog(),
            new Cat(),
            new Animal()
        };
        
        // Same method call, different behaviors
        for (Animal animal : animals) {
            animal.makeSound(); // Polymorphic call
        }
    }
}

4. Abstraction ๐Ÿ“
#

Definition: Hiding complex implementation details, showing only essential features.

Ways to Achieve Abstraction:
#

A. Abstract Classes
#

// Abstract class - cannot be instantiated
public abstract class Shape {
    protected String color;
    
    public Shape(String color) {
        this.color = color;
    }
    
    // Concrete method - has implementation
    public void displayColor() {
        System.out.println("Color: " + color);
    }
    
    // Abstract method - must be implemented by subclasses
    public abstract double calculateArea();
    public abstract double calculatePerimeter();
}

// Concrete class implementing abstract methods
public class Rectangle extends Shape {
    private double width, height;
    
    public Rectangle(String color, double width, double height) {
        super(color);
        this.width = width;
        this.height = height;
    }
    
    @Override
    public double calculateArea() {
        return width * height;
    }
    
    @Override
    public double calculatePerimeter() {
        return 2 * (width + height);
    }
}

public class Circle extends Shape {
    private double radius;
    
    public Circle(String color, double radius) {
        super(color);
        this.radius = radius;
    }
    
    @Override
    public double calculateArea() {
        return Math.PI * radius * radius;
    }
    
    @Override
    public double calculatePerimeter() {
        return 2 * Math.PI * radius;
    }
}

B. Interface-based Abstraction
#

// Interface - pure abstraction
public interface Drawable {
    void draw();
    void resize(double factor);
}

public class Circle implements Drawable {
    @Override
    public void draw() {
        System.out.println("Drawing a circle");
    }
    
    @Override
    public void resize(double factor) {
        System.out.println("Resizing circle by factor: " + factor);
    }
}

layout: default
#

Hands-on Exercise 1: Student Class Creation
#

Exercise: Create Student Management System
#

Create a Student class with the following requirements:

Requirements:
#

  1. Attributes: enrollmentNo (String), name (String), marks (double)
  2. Constructor: Initialize all attributes
  3. Methods:
    • displayInfo(): Show student details
    • getGrade(): Return grade based on marks
    • updateMarks(double newMarks): Update student marks
    • isPass(): Return true if marks >= 35

Grading System:
#

  • A: 90-100
  • B: 80-89
  • C: 70-79
  • D: 60-69
  • E: 35-59
  • F: Below 35

Test Cases:
#

Create 3 student objects and demonstrate all methods.

// Your implementation here
public class Student {
    // Add attributes
    
    // Add constructor
    
    // Add methods
}

public class StudentTest {
    public static void main(String[] args) {
        // Create objects and test methods
    }
}

Solution:
#

public class Student {
    private String enrollmentNo;
    private String name;
    private double marks;
    
    // Constructor
    public Student(String enrollmentNo, String name, double marks) {
        this.enrollmentNo = enrollmentNo;
        this.name = name;
        this.marks = marks;
    }
    
    // Display student information
    public void displayInfo() {
        System.out.println("=== Student Information ===");
        System.out.println("Enrollment No: " + enrollmentNo);
        System.out.println("Name: " + name);
        System.out.println("Marks: " + marks);
        System.out.println("Grade: " + getGrade());
        System.out.println("Status: " + (isPass() ? "PASS" : "FAIL"));
    }
    
    // Calculate grade based on marks
    public char getGrade() {
        if (marks >= 90) return 'A';
        else if (marks >= 80) return 'B';
        else if (marks >= 70) return 'C';
        else if (marks >= 60) return 'D';
        else if (marks >= 35) return 'E';
        else return 'F';
    }
    
    // Update student marks
    public void updateMarks(double newMarks) {
        if (newMarks >= 0 && newMarks <= 100) {
            this.marks = newMarks;
            System.out.println("Marks updated to: " + newMarks);
        } else {
            System.out.println("Invalid marks! Must be between 0-100");
        }
    }
    
    // Check if student has passed
    public boolean isPass() {
        return marks >= 35;
    }
    
    // Getter methods
    public String getEnrollmentNo() { return enrollmentNo; }
    public String getName() { return name; }
    public double getMarks() { return marks; }
}

Test Class:
#

public class StudentTest {
    public static void main(String[] args) {
        // Create three students
        Student student1 = new Student("201901001", "John Doe", 85.5);
        Student student2 = new Student("201901002", "Jane Smith", 92.0);
        Student student3 = new Student("201901003", "Bob Johnson", 32.5);
        
        // Display initial information
        student1.displayInfo();
        student2.displayInfo();
        student3.displayInfo();
        
        // Update marks and show changes
        System.out.println("\n=== Updating Marks ===");
        student3.updateMarks(65.0);
        student3.displayInfo();
        
        // Demonstrate pass/fail checking
        System.out.println("\n=== Pass/Fail Status ===");
        System.out.println(student1.getName() + ": " + 
                         (student1.isPass() ? "PASSED" : "FAILED"));
        System.out.println(student2.getName() + ": " + 
                         (student2.isPass() ? "PASSED" : "FAILED"));
        System.out.println(student3.getName() + ": " + 
                         (student3.isPass() ? "PASSED" : "FAILED"));
    }
}

layout: default
#

Hands-on Exercise 2: Vehicle Hierarchy
#

Exercise: Create Vehicle Inheritance System
#

Requirements:
#

Create a vehicle hierarchy demonstrating inheritance:

Base Class: Vehicle
#

  • Attributes: brand (String), maxSpeed (int), currentSpeed (int)
  • Methods:
    • start(): Display start message
    • accelerate(int speed): Increase current speed
    • brake(int speed): Decrease current speed
    • displayInfo(): Show vehicle details

Derived Class: Car extends Vehicle
#

  • Additional Attributes: numberOfDoors (int), fuelType (String)
  • Additional Methods:
    • honk(): Car-specific sound
    • openTrunk(): Car-specific action
  • Override: start() method with car-specific message

Derived Class: Motorcycle extends Vehicle
#

  • Additional Attributes: hasCarrier (boolean), engineType (String)
  • Additional Methods:
    • wheelie(): Motorcycle-specific action
    • putOnHelmet(): Safety method
  • Override: start() method with motorcycle-specific message

Test Requirements:
#

  1. Create objects of Car and Motorcycle
  2. Demonstrate inheritance (calling parent methods)
  3. Demonstrate method overriding
  4. Show polymorphic behavior

Solution:
#

// Base class
public class Vehicle {
    protected String brand;
    protected int maxSpeed;
    protected int currentSpeed;
    
    public Vehicle(String brand, int maxSpeed) {
        this.brand = brand;
        this.maxSpeed = maxSpeed;
        this.currentSpeed = 0;
    }
    
    public void start() {
        System.out.println(brand + " vehicle is starting...");
        currentSpeed = 0;
    }
    
    public void accelerate(int speed) {
        if (currentSpeed + speed <= maxSpeed) {
            currentSpeed += speed;
            System.out.println("Accelerated to: " + currentSpeed + " km/h");
        } else {
            System.out.println("Cannot exceed max speed of " + maxSpeed + " km/h");
        }
    }
    
    public void brake(int speed) {
        currentSpeed = Math.max(0, currentSpeed - speed);
        System.out.println("Speed reduced to: " + currentSpeed + " km/h");
    }
    
    public void displayInfo() {
        System.out.println("Brand: " + brand);
        System.out.println("Max Speed: " + maxSpeed + " km/h");
        System.out.println("Current Speed: " + currentSpeed + " km/h");
    }
}

// Car class
public class Car extends Vehicle {
    private int numberOfDoors;
    private String fuelType;
    
    public Car(String brand, int maxSpeed, int doors, String fuelType) {
        super(brand, maxSpeed);
        this.numberOfDoors = doors;
        this.fuelType = fuelType;
    }
    
    @Override
    public void start() {
        System.out.println(brand + " car engine started with a gentle hum");
        currentSpeed = 0;
    }
    
    public void honk() {
        System.out.println(brand + " car: BEEP BEEP!");
    }
    
    public void openTrunk() {
        System.out.println("Opening " + brand + " car trunk");
    }
    
    @Override
    public void displayInfo() {
        super.displayInfo();
        System.out.println("Number of Doors: " + numberOfDoors);
        System.out.println("Fuel Type: " + fuelType);
    }
}

Motorcycle Class:
#

public class Motorcycle extends Vehicle {
    private boolean hasCarrier;
    private String engineType;
    
    public Motorcycle(String brand, int maxSpeed, boolean hasCarrier, String engineType) {
        super(brand, maxSpeed);
        this.hasCarrier = hasCarrier;
        this.engineType = engineType;
    }
    
    @Override
    public void start() {
        System.out.println(brand + " motorcycle roars to life!");
        currentSpeed = 0;
    }
    
    public void wheelie() {
        if (currentSpeed > 20) {
            System.out.println("Performing wheelie on " + brand + " motorcycle!");
        } else {
            System.out.println("Need more speed for wheelie");
        }
    }
    
    public void putOnHelmet() {
        System.out.println("Safety first! Helmet is on.");
    }
    
    @Override
    public void displayInfo() {
        super.displayInfo();
        System.out.println("Has Carrier: " + (hasCarrier ? "Yes" : "No"));
        System.out.println("Engine Type: " + engineType);
    }
}

Test Class:
#

public class VehicleTest {
    public static void main(String[] args) {
        // Create objects
        Car myCar = new Car("Toyota", 180, 4, "Petrol");
        Motorcycle myBike = new Motorcycle("Honda", 220, true, "4-Stroke");
        
        System.out.println("=== CAR DEMONSTRATION ===");
        myCar.start();           // Overridden method
        myCar.accelerate(50);    // Inherited method
        myCar.honk();           // Car-specific method
        myCar.displayInfo();    // Overridden method
        myCar.openTrunk();      // Car-specific method
        
        System.out.println("\n=== MOTORCYCLE DEMONSTRATION ===");
        myBike.putOnHelmet();   // Bike-specific method
        myBike.start();         // Overridden method
        myBike.accelerate(30);  // Inherited method
        myBike.wheelie();       // Bike-specific method
        myBike.displayInfo();   // Overridden method
        
        System.out.println("\n=== POLYMORPHISM DEMONSTRATION ===");
        Vehicle[] vehicles = {myCar, myBike};
        
        for (Vehicle vehicle : vehicles) {
            vehicle.start();        // Calls appropriate overridden method
            vehicle.accelerate(25); // Inherited method
            vehicle.displayInfo();  // Calls appropriate overridden method
            System.out.println();
        }
    }
}

layout: default
#

Benefits of Object-Oriented Programming
#

Code Organization Benefits
#

1. Modularity
#

// Each class is a separate module
public class BankAccount {
    // Account-related functionality only
}

public class Customer {
    // Customer-related functionality only  
}

public class Transaction {
    // Transaction-related functionality only
}

public class BankingSystem {
    // Coordinates different modules
    private List<Customer> customers;
    private List<BankAccount> accounts;
    private List<Transaction> transactions;
}

2. Reusability
#

// Base Employee class can be reused
public class Employee {
    protected String name, id;
    protected double salary;
    
    public void displayInfo() {
        System.out.println("ID: " + id + ", Name: " + name);
    }
}

// Reused in different contexts
public class Manager extends Employee {
    private int teamSize;
}

public class Developer extends Employee {
    private String programmingLanguage;
}

public class SalesRepresentative extends Employee {
    private double commissionRate;
}

3. Maintainability
#

// Changes in one class don't affect others
public class EmailService {
    public void sendEmail(String to, String subject, String body) {
        // If email logic changes, only this class needs modification
        // Other classes using this remain unchanged
    }
}

public class NotificationManager {
    private EmailService emailService = new EmailService();
    
    public void notifyUser(String email, String message) {
        emailService.sendEmail(email, "Notification", message);
        // This code remains the same even if EmailService changes internally
    }
}

Design Benefits
#

4. Flexibility and Extensibility
#

// Easy to add new shapes without changing existing code
public abstract class Shape {
    public abstract double getArea();
}

public class Rectangle extends Shape {
    public double getArea() { return width * height; }
}

public class Circle extends Shape {
    public double getArea() { return Math.PI * radius * radius; }
}

// Adding new shape doesn't break existing code
public class Triangle extends Shape {
    public double getArea() { return 0.5 * base * height; }
}

// Client code works with any shape
public class AreaCalculator {
    public double getTotalArea(Shape[] shapes) {
        double total = 0;
        for (Shape shape : shapes) {
            total += shape.getArea(); // Polymorphism in action
        }
        return total;
    }
}

5. Problem-Solving Approach
#

// Models real-world entities naturally
public class Library {
    private List<Book> books;
    private List<Member> members;
    
    // Real-world operations
    public void issueBook(Member member, Book book) {
        if (book.isAvailable() && member.canBorrowMore()) {
            book.setIssued(true, member, new Date());
            member.addBorrowedBook(book);
        }
    }
    
    public void returnBook(Member member, Book book) {
        book.setAvailable();
        member.removeBorrowedBook(book);
        // Calculate fine if overdue
    }
}

6. Team Development
#

// Different developers can work on different classes simultaneously

// Developer A works on User Management
public class User {
    // User-related functionality
}

// Developer B works on Product Management  
public class Product {
    // Product-related functionality
}

// Developer C works on Order Management
public class Order {
    // Order-related functionality
}

// All can be integrated later through interfaces
public interface OrderProcessor {
    void processOrder(User user, List<Product> products);
}

layout: default
#

Common OOP Mistakes and Best Practices
#

Common Mistakes to Avoid
#

1. Breaking Encapsulation
#

// BAD: Public fields
public class BadStudent {
    public String name;      // Anyone can modify
    public double marks;     // No validation possible
    
    public void setMarks(double marks) {
        this.marks = marks;  // Direct assignment, no validation
    }
}

// GOOD: Proper encapsulation
public class GoodStudent {
    private String name;     // Protected from direct access
    private double marks;    // Controlled access only
    
    public void setMarks(double marks) {
        if (marks >= 0 && marks <= 100) {
            this.marks = marks;
        } else {
            throw new IllegalArgumentException("Marks must be between 0-100");
        }
    }
    
    public double getMarks() {
        return marks;
    }
}

2. Poor Inheritance Design
#

// BAD: Inheritance for code reuse only
public class Animal {
    public void eat() { /* eating logic */ }
    public void sleep() { /* sleeping logic */ }
    public void fly() { /* flying logic - not all animals fly! */ }
}

public class Dog extends Animal {
    // Dog inherits fly() method which doesn't make sense
}

// GOOD: Proper inheritance hierarchy
public class Animal {
    public void eat() { /* eating logic */ }
    public void sleep() { /* sleeping logic */ }
}

public class Bird extends Animal {
    public void fly() { /* flying logic specific to birds */ }
}

public class Dog extends Animal {
    public void bark() { /* dog-specific behavior */ }
}

Best Practices
#

1. Follow Naming Conventions
#

// GOOD naming conventions
public class BankAccount {           // PascalCase for classes
    private double accountBalance;   // camelCase for variables
    private static final int MAX_WITHDRAWAL_LIMIT = 10000; // UPPER_CASE for constants
    
    public void depositMoney(double amount) {  // camelCase for methods
        // Method implementation
    }
    
    public double getAccountBalance() {        // Descriptive method names
        return accountBalance;
    }
}

2. Design for Single Responsibility
#

// GOOD: Each class has single responsibility
public class Customer {
    // Only customer data and basic operations
    private String customerId;
    private String name;
    private String email;
}

public class CustomerValidator {
    // Only validation logic
    public boolean isValidEmail(String email) {
        return email.contains("@") && email.contains(".");
    }
}

public class CustomerDatabase {
    // Only database operations
    public void saveCustomer(Customer customer) {
        // Database save logic
    }
    
    public Customer findCustomer(String id) {
        // Database search logic
        return null;
    }
}

public class CustomerService {
    // Coordinates between different components
    private CustomerValidator validator;
    private CustomerDatabase database;
    
    public void createCustomer(String name, String email) {
        if (validator.isValidEmail(email)) {
            Customer customer = new Customer(name, email);
            database.saveCustomer(customer);
        }
    }
}

3. Use Composition Over Inheritance When Appropriate
#

// Instead of inheritance
public class Car {
    private Engine engine;      // HAS-A relationship
    private Transmission transmission;
    private GPS gpsSystem;
    
    public void start() {
        engine.start();         // Delegate to composed objects
    }
    
    public void navigate(String destination) {
        gpsSystem.findRoute(destination);
    }
}

layout: default
#

Real-world Applications
#

1. E-commerce System Design
#

// Product catalog management
public class Product {
    private String productId;
    private String name;
    private double price;
    private int stockQuantity;
    private Category category;
    
    public boolean isInStock() {
        return stockQuantity > 0;
    }
    
    public void reduceStock(int quantity) {
        if (quantity <= stockQuantity) {
            stockQuantity -= quantity;
        } else {
            throw new IllegalArgumentException("Insufficient stock");
        }
    }
}

// Shopping cart functionality
public class ShoppingCart {
    private Map<Product, Integer> items;
    private Customer customer;
    
    public void addItem(Product product, int quantity) {
        if (product.isInStock() && quantity > 0) {
            items.put(product, items.getOrDefault(product, 0) + quantity);
        }
    }
    
    public double calculateTotal() {
        return items.entrySet().stream()
                   .mapToDouble(entry -> entry.getKey().getPrice() * entry.getValue())
                   .sum();
    }
    
    public Order checkout() {
        // Create order and process payment
        return new Order(customer, new ArrayList<>(items.entrySet()));
    }
}

// Order management
public class Order {
    private String orderId;
    private Customer customer;
    private List<OrderItem> items;
    private OrderStatus status;
    private Date orderDate;
    
    public void processOrder() {
        status = OrderStatus.PROCESSING;
        // Process payment, update inventory, send confirmation
    }
}

2. Student Information System
#

// Academic management
public class Course {
    private String courseCode;
    private String courseName;
    private int credits;
    private Professor professor;
    
    public void enrollStudent(Student student) {
        if (student.canEnroll(this)) {
            student.addCourse(this);
        }
    }
}

public class Student {
    private String enrollmentNo;
    private String name;
    private List<Course> enrolledCourses;
    private Map<Course, Grade> grades;
    
    public double calculateGPA() {
        double totalPoints = 0;
        int totalCredits = 0;
        
        for (Map.Entry<Course, Grade> entry : grades.entrySet()) {
            Course course = entry.getKey();
            Grade grade = entry.getValue();
            totalPoints += grade.getPoints() * course.getCredits();
            totalCredits += course.getCredits();
        }
        
        return totalCredits > 0 ? totalPoints / totalCredits : 0.0;
    }
    
    public List<Course> getEligibleCourses() {
        // Return courses student can enroll in based on prerequisites
        return new ArrayList<>();
    }
}

// Academic record management
public class Transcript {
    private Student student;
    private List<AcademicRecord> records;
    
    public void generateTranscript() {
        // Generate official transcript
        System.out.println("Transcript for: " + student.getName());
        System.out.println("GPA: " + student.calculateGPA());
        
        for (AcademicRecord record : records) {
            System.out.println(record.getCourse().getCourseName() + 
                             " - " + record.getGrade());
        }
    }
}

3. Banking System Architecture
#

// Account hierarchy
public abstract class Account {
    protected String accountNumber;
    protected double balance;
    protected Customer owner;
    
    public abstract void withdraw(double amount);
    public abstract double calculateInterest();
}

public class SavingsAccount extends Account {
    private double interestRate;
    private int freeTransactionsPerMonth;
    
    @Override
    public void withdraw(double amount) {
        if (balance - amount >= 1000) { // Minimum balance
            balance -= amount;
        } else {
            throw new InsufficientFundsException("Minimum balance required");
        }
    }
    
    @Override
    public double calculateInterest() {
        return balance * interestRate / 100 / 12; // Monthly interest
    }
}

public class CurrentAccount extends Account {
    private double overdraftLimit;
    
    @Override
    public void withdraw(double amount) {
        if (balance + overdraftLimit >= amount) {
            balance -= amount;
        } else {
            throw new InsufficientFundsException("Overdraft limit exceeded");
        }
    }
    
    @Override
    public double calculateInterest() {
        return 0; // No interest for current accounts
    }
}

layout: default
#

Summary and Key Takeaways
#

What We Learned
#

  • ๐ŸŽฏ OOP Fundamentals: Understanding classes, objects, and their relationships
  • ๐Ÿ”’ Encapsulation: Data hiding and controlled access through methods
  • ๐Ÿงฌ Inheritance: Code reusability through parent-child relationships
  • ๐ŸŽญ Polymorphism: Same interface, multiple implementations
  • ๐Ÿ“ Abstraction: Hiding complexity, showing only essential features
  • ๐Ÿ› ๏ธ Practical Implementation: Creating real-world applications using OOP

Core Concepts Review
#

Classes and Objects
#

  • Class: Blueprint for creating objects
  • Object: Instance of a class with specific data
  • Constructor: Special method for object initialization
  • Methods: Define object behavior

Four Pillars of OOP
#

  1. Encapsulation: Data protection and controlled access
  2. Inheritance: Building new classes from existing ones
  3. Polymorphism: Multiple forms of the same interface
  4. Abstraction: Simplifying complex systems

Benefits Achieved
#

  • Code Organization: Better structure and modularity
  • Reusability: Write once, use multiple times
  • Maintainability: Easier to modify and debug
  • Scalability: Easy to extend functionality
  • Team Development: Multiple developers can work simultaneously

Best Practices Learned
#

  • Naming Conventions: Use meaningful, consistent names
  • Single Responsibility: Each class should have one purpose
  • Encapsulation: Keep data private, provide public methods
  • Composition over Inheritance: Prefer HAS-A over IS-A when appropriate
  • Method Design: Small, focused methods with clear purposes
  • Validation: Always validate input parameters
  • Documentation: Comment your classes and complex methods

Real-world Applications
#

Systems We Can Now Design
#

  • Student Management System: Academic records and enrollment
  • Banking System: Accounts, transactions, and customer management
  • E-commerce Platform: Products, shopping cart, and orders
  • Library Management: Books, members, and borrowing system
  • Inventory Management: Products, stock, and suppliers

Next Steps
#

In upcoming lectures, we will:

  • Deep dive into Classes and Objects (Lecture 11)
  • Master Access Modifiers (Lecture 12)
  • Explore Java Keywords (Lecture 13)
  • Work with Constructors (Lecture 14)
  • Implement Method Overloading (Lecture 15)

Preparation for Next Class
#

  • Review today’s examples
  • Practice creating simple classes
  • Think about real-world objects and their properties
  • Prepare questions about OOP concepts

layout: center class: text-center
#

Thank You!
#

OOP Fundamentals Complete
#

Lecture 10 Successfully Completed!
You now understand the foundation of Object-Oriented Programming in Java

Ready to dive deeper into classes and objects!