CSC166 Object Oriented Programming

Object Oriented ProgrammingUnit 115 min read

OOP Core Concepts: Models, Paradigms, and Real-World Abstraction

Unit 1 of Object Oriented Programming introduces the foundational principles of OOP—abstraction, encapsulation, inheritance, polymorphism, and modularity—through definitions, real-world analogies, and comparisons with procedural programming. It explains how OOP models real-world entities as objects, contrasts OOP vs. p

TAKEAWAYS:

  • OOP models the real world as objects (data + behavior) that interact via messages, unlike procedural code’s step-by-step instructions.
  • The four pillars (abstraction, encapsulation, inheritance, polymorphism) solve problems like code reuse, scalability, and maintainability.
  • Encapsulation hides data (e.g., a BankAccount’s balance) and exposes only safe methods (e.g., deposit()), preventing invalid states.
  • Inheritance lets classes reuse/extend others (e.g., ElectricVehicle inherits from Vehicle), reducing redundant code.
  • Polymorphism enables one interface (e.g., sound()) to work across different objects (e.g., Dog, Cat), critical for frameworks like eSewa’s payment handlers.
  • OOP’s modularity isolates components (e.g., Daraz’s order-processing module), making systems easier to debug and update.

1. What is Object-Oriented Programming?

OOP is a paradigm (programming approach) that organizes software into objects—self-contained units combining data (attributes) and behavior (methods). Unlike procedural programming (which focuses on functions), OOP mimics real-world entities and their interactions.

Key Definitions

Term Definition Example
Object An instance of a class (e.g., a User in eSewa with name and balance). user1 = User("Ram", 5000)
Class A blueprint for objects (e.g., User defines all users’ structure). class User { string name; int balance; }
Method A function inside a class that operates on its data (e.g., transfer() moves money between accounts). void transfer(User recipient, int amount) { ... }
Attribute Data stored in an object (e.g., NcellCustomer.balance). private int balance;
Message A request to an object to perform an action (e.g., account.withdraw(100)). account.deposit(500);

Why OOP?

  • Real-world modeling: Objects represent tangible things (e.g., a PathaoRide has driver, passenger, fare).
  • Reusability: Inheritance avoids rewriting code (e.g., ElectricVehicle reuses Vehicle’s startEngine()).
  • Scalability: Large systems (e.g., NEPSE’s trading platform) manage complexity via modular objects.
  • Maintainability: Encapsulation limits unintended changes (e.g., BankAccount hides balance from direct access).

2. The Four Pillars of OOP

Visualize how these pillars work together in a bank transaction system (like Nabil Bank’s app):

classDiagram
    class Account {
        <<abstract>>
        +String owner
        +double balance
        +void deposit(double amount)
        +void withdraw(double amount)
    }
    class SavingsAccount {
        +double interestRate
        +void addInterest()
    }
    class CurrentAccount {
        +double overdraftLimit
    }
    Account <|-- SavingsAccount
    Account <|-- CurrentAccount
    class Transaction {
        +Account from
        +Account to
        +double amount
        +void execute()
    }
    Transaction --> Account : transfers money

A. Abstraction

Definition: Hiding complex implementation details and exposing only essential features. How it works:

  • Use abstract classes (e.g., Account) or interfaces (e.g., IPayable) to define "what" an object does, not "how."
  • Example: A PaymentGateway in eSewa knows processPayment() exists but doesn’t need to know if it uses Khalti or credit cards.

Real-world analogy:

  • Ncell’s billing system: Users see payBill() but don’t know if it calls SMS, IVR, or the app backend.

B. Encapsulation

Definition: Bundling data and methods that operate on it, while restricting direct access to data. How it works:

  • Use access modifiers (private, public, protected) to control visibility.
  • Provide getter/setter methods to validate data (e.g., prevent negative balance).
class BankAccount {
private:    // Hidden from outside
    double balance;
public:     // Accessible
    void deposit(double amount) {
        if (amount > 0) balance += amount;
    }
    double getBalance() { return balance; }  // Safe access
};

Visual: State after deposit(500)


C. Inheritance

Definition: A mechanism where a derived class inherits properties/methods from a base class. Types of Inheritance (with Nepali tech examples):

Type Description Example
Single One base class → one derived class. ElectricVehicle inherits from Vehicle.
Multilevel Chain of inheritance (A → B → C). TwoWheeler → Bike → ElectricBike.
Hierarchical One base class → multiple derived classes. PaymentMethod → CreditCard, DebitCard, MobileWallet (eSewa uses this).
Multiple One derived class inherits from two base classes (C++ doesn’t support this directly). Not used in C++ (use interfaces instead).
Hybrid Combination of hierarchical + multilevel. Vehicle → Car and Bike; Car → ElectricCar.

Code Example: Hierarchical Inheritance in Ncell Billing

class Customer {
protected:
    string name;
public:
    void setName(string n) { name = n; }
};
class PrepaidCustomer : public Customer {};
class PostpaidCustomer : public Customer {};

D. Polymorphism

Definition: The ability to process objects differently based on their data type or state. Types:

  1. Compile-time (Operator Overloading):
    • Redefine operators (e.g., + for Distance objects).
    • Example: Adding two Time objects (e.g., 3:30 + 1:45 = 5:15).
  2. Run-time (Function Overriding):
    • Derived classes redefine base class methods.
    • Example: Animal.sound() → Dog returns "bark," Cat returns "meow."

Real-world example:

  • eSewa’s payment system: The same processPayment() method works for Khalti, credit cards, and bank transfers via polymorphism.

Code Example: Function Overriding

class Animal {
public:
    virtual void sound() { cout << "Animal sound"; }
};
class Dog : public Animal {
public:
    void sound() override { cout << "Bark!"; }  // Overrides base class
};

3. OOP vs. Procedural Programming

Compare how OOP and procedural programming solve the same problem: managing a library’s book inventory.

Feature Procedural Programming (C) Object-Oriented Programming (C++)
Focus Functions and data structures. Objects and their interactions.
Code Organization Linear, top-down (e.g., addBook(), searchBook()). Modular (e.g., Book class with add(), search()).
Data Access Global variables or passed explicitly. Encapsulated within objects.
Reusability Limited (copy-paste code). High (inheritance, polymorphism).
Example void addBook(char* title, int id) Library.addBook(Book("C++", 101));

Visual: Procedural vs. OOP for Book Management

flowchart LR
    subgraph Procedural
        A["main()"] --> B["addBook(title, id)"]
        A --> C["searchBook(id)"]
        D[(Global array: books[100])]
    end
    subgraph OOP
        E["Library"] --> F["Book objects"]
        F --> G["title: string\nid: int"]
        E -->|"methods"| H["addBook(Book)\nsearchBook(int)"]
    end

4. Real-World Applications in Nepal

A. eSewa’s Transaction System

  • Abstraction: Users interact with payBill() without knowing it calls KhaltiGateway or BankGateway.
  • Encapsulation: UserAccount hides balance; only deposit()/withdraw() can modify it.
  • Inheritance: PaymentMethod → MobileWallet, CreditCard, DebitCard.
  • Polymorphism: processPayment() behaves differently for each payment type.

B. Pathao’s Ride Matching

  • Objects: Driver, Passenger, Ride, Payment.
  • Polymorphism: Ride.calculateFare() uses different logic for bike vs. car rides.
  • Encapsulation: Driver.location is private; only updateLocation() can change it.

C. Ncell’s Billing System

  • Inheritance: Customer → PrepaidCustomer, PostpaidCustomer.
  • Abstraction: BillGenerator defines generateBill() without specifying SMS/IVR/email.

5. Worked Example: Animal Sound System

Problem: Implement a system where Dog, Cat, and Snake make different sounds using polymorphism.

Solution:

#include <iostream>
using namespace std;

class Animal {
public:
    virtual void makeSound() { cout << "Some generic sound"; }
    virtual ~Animal() {}  // Virtual destructor for safe deletion
};

class Dog : public Animal {
public:
    void makeSound() override { cout << "Raf - raf"; }
};

class Cat : public Animal {
public:
    void makeSound() override { cout << "Meow"; }
};

class Snake : public Animal {
public:
    void makeSound() override { cout << "Hiss"; }
};

int main() {
    Animal* animals[3] = {new Dog(), new Cat(), new Snake()};
    for (int i = 0; i < 3; i++) {
        animals[i]->makeSound();  // Polymorphic call
        delete animals[i];
    }
    return 0;
}

Output:

Raf - raf
Meow
Hiss

Visual: Polymorphism in Action

sequenceDiagram
    participant Main as main()
    participant AnimalArray as Animal*[3]
    Main->>AnimalArray: animals[0]->makeSound()
    AnimalArray->>Dog: Raf - raf
    Main->>AnimalArray: animals[1]->makeSound()
    AnimalArray->>Cat: Meow
    Main->>AnimalArray: animals[2]->makeSound()
    AnimalArray->>Snake: Hiss

6. Common Pitfalls and Best Practices

Pitfall Solution
Overusing inheritance Prefer composition (e.g., Car has an Engine object) over deep inheritance hierarchies.
Exposing private data Always use getters/setters to validate data (e.g., setAge() checks for negative values).
Tight coupling Design classes to depend on abstractions (e.g., IPaymentGateway), not concrete classes.
Ignoring virtual destructors Always declare virtual ~ClassName() to prevent memory leaks when deleting derived objects.

7. Exam Tip: How to Score Full Marks

  1. Define terms precisely:
    • Example: "Encapsulation is the mechanism of binding data and methods into a single unit (class) while restricting direct access to some of the object’s components." (2 marks)
  2. Use UML diagrams for inheritance/polymorphism:
    • Draw a class diagram with arrows (<|-- for inheritance, ..> for composition).
  3. Relate to real-world systems:
    • Example: "In eSewa, polymorphism allows the processPayment() method to handle Khalti, credit cards, and bank transfers differently." (3 marks)
  4. Code snippets with explanations:
    • Always include a short code example (3–5 lines) and trace its output.
  5. Compare OOP vs. procedural:
    • Use a table (like above) to highlight differences in code organization, reusability, and data access. (4 marks)
  6. Avoid vague answers:
    • ❌ "Inheritance is used to reuse code."
    • ✅ "Hierarchical inheritance in Ncell’s system lets PrepaidCustomer and PostpaidCustomer reuse the Customer class’s setName() method while adding their own calculateBill() logic." (5 marks)

8. Past Exam Questions Solved

Q1: Implement animal sounds using pure virtual functions.

class Animal {
public:
    virtual void makeSound() = 0;  // Pure virtual function
    virtual ~Animal() {}
};
class Dog : public Animal {
public:
    void makeSound() override { cout << "Raf - raf"; }
};
// Similarly for Cat and Snake.

Q2: Types of inheritance with examples.

Type Example
Single ElectricVehicle inherits from Vehicle.
Multilevel TwoWheeler → Bike → ElectricBike.
Hierarchical PaymentMethod → CreditCard, DebitCard, MobileWallet (used in eSewa).
Hybrid Vehicle → Car and Bike; Car → ElectricCar.

Q3: Class BOOK with lower-price comparison.

class Book {
private:
    string name;
    double price;
public:
    Book(string n, double p) : name(n), price(p) {}
    bool isCheaperThan(const Book& other) {
        return price < other.price;
    }
};
// Usage:
Book b1("C++", 500), b2("Java", 600);
if (b1.isCheaperThan(b2)) cout << b1.name << " is cheaper.";

9. Summary Checklist

Before the exam, ensure you can:

  1. Define class, object, method, and encapsulation.
  2. Draw a class diagram with inheritance and polymorphism.
  3. Write code for:
    • A class with private data and public methods.
    • Inheritance (single/multilevel/hierarchical).
    • Polymorphism (virtual functions/operator overloading).
  4. Explain OOP vs. procedural programming with examples.
  5. Relate OOP concepts to Nepali tech (eSewa, Ncell, Daraz, banks).

Based on the TU BSc CSIT syllabus for Object Oriented Programming (CSC166), unit 1.

Discussion

Loading…