OOP Fundamentals#
Lecture 10#
Java Programming (4343203)
Diploma in ICT - Semester IV
Gujarat Technological University
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:#
- Attributes: enrollmentNo (String), name (String), marks (double)
- Constructor: Initialize all attributes
- Methods:
displayInfo(): Show student detailsgetGrade(): Return grade based on marksupdateMarks(double newMarks): Update student marksisPass(): 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 messageaccelerate(int speed): Increase current speedbrake(int speed): Decrease current speeddisplayInfo(): Show vehicle details
Derived Class: Car extends Vehicle#
- Additional Attributes: numberOfDoors (int), fuelType (String)
- Additional Methods:
honk(): Car-specific soundopenTrunk(): 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 actionputOnHelmet(): Safety method
- Override:
start()method with motorcycle-specific message
Test Requirements:#
- Create objects of Car and Motorcycle
- Demonstrate inheritance (calling parent methods)
- Demonstrate method overriding
- 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#
- Encapsulation: Data protection and controlled access
- Inheritance: Building new classes from existing ones
- Polymorphism: Multiple forms of the same interface
- 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

