Computer Science Basics Course (CS101) – Module 5
Module 5: Object-Oriented Programming (OOP)
- Principles of OOP (encapsulation, inheritance, polymorphism)
Introduction:
Object-Oriented Programming (OOP) is a programming paradigm that revolves around the concept of objects, which represent real-world entities, and their interactions. OOP principles provide guidelines for structuring code in a modular and scalable way. In this lesson, we will explore three fundamental principles of OOP: encapsulation, inheritance, and polymorphism.
- Encapsulation:
Definition: Encapsulation is the bundling of data and methods that operate on the data within a single unit, called a class. It hides the internal state of an object and only exposes the necessary functionalities through well-defined interfaces.
Benefits:
Data Hiding: Encapsulation prevents direct access to an object’s internal state, which helps maintain data integrity and reduces the risk of unintended modifications.
Abstraction: Encapsulation allows developers to focus on the essential aspects of an object’s behavior without being concerned with its implementation details.
Example: Consider a class Car with private attributes model and year, and public methods get_model() and get_year() to access these attributes.
- Inheritance:
Definition: Inheritance is a mechanism that allows a class (subclass) to inherit properties and behaviors (methods) from another class (superclass). It promotes code reuse and establishes a hierarchical relationship between classes.
Types:
Single Inheritance: A subclass inherits from a single superclass.
Multiple Inheritance: A subclass inherits from multiple superclasses (not supported in all programming languages).
Multilevel Inheritance: A subclass serves as the superclass for another subclass, creating a hierarchy.
Example: Consider a superclass Shape with methods area() and perimeter(), and subclasses Rectangle and Circle that inherit from Shape and implement their specific implementations of these methods.
- Polymorphism:
Definition: Polymorphism allows objects of different classes to be treated as objects of a common superclass. It enables flexibility and extensibility by allowing methods to behave differently based on the object they are invoked on.
Types:
Compile-time Polymorphism (Method Overloading): Multiple methods with the same name but different parameter lists within the same class.
Runtime Polymorphism (Method Overriding): Subclasses provide a specific implementation of a method defined in the superclass.
Example: Consider a superclass Animal with a method make_sound(), and subclasses Dog and Cat that override make_sound() to produce their respective sounds.
- Practice Exercise:
Problem: Design a class hierarchy for a banking system that includes Account (superclass) and subclasses SavingsAccount, CheckingAccount, and LoanAccount.
Solution: Use inheritance to define common attributes and behaviors in the Account class and specific features in each subclass, such as interest rates for savings accounts and overdraft limits for checking accounts.
- Advantages and Considerations:
Advantages:
OOP promotes code reusability, modularity, and maintainability.
Encapsulation hides implementation details, reducing complexity and enhancing security.
Inheritance facilitates code organization and promotes the reuse of existing code.
Polymorphism allows for flexible and extensible code by enabling dynamic method invocation.
Considerations:
Proper design and implementation are crucial to leveraging OOP principles effectively.
Overuse of inheritance can lead to tight coupling and code fragility.
Polymorphism can make code harder to understand if not used appropriately.
- OOP concepts in Python/Java/C++
Introduction:
Object-Oriented Programming (OOP) is a programming paradigm that revolves around the concept of objects, which represent real-world entities, and their interactions. OOP promotes modularity, reusability, and maintainability by organizing code into classes and objects. In this lesson, we will explore how OOP concepts are implemented in Python, Java, and C++.
- Classes and Objects:
Python: In Python, classes are defined using the class keyword, and objects are instances of these classes. Attributes and methods are defined within the class using the self parameter.
class Car:
def __init__(self, make, model):
self.make = make
self.model = model
def display_info(self):
print(f”Make: {self.make}, Model: {self.model}”)
car1 = Car(“Toyota”, “Corolla”)
car1.display_info()
Java: In Java, classes are defined using the class keyword, and objects are created using the new keyword followed by the class constructor. Attributes and methods are defined within the class using access modifiers like public, private, or protected.
public class Car {
private String make;
private String model;
public Car(String make, String model) {
this.make = make;
this.model = model;
}
public void displayInfo() {
System.out.println(“Make: ” + make + “, Model: ” + model);
}
}
Car car1 = new Car(“Toyota”, “Corolla”);
car1.displayInfo();
C++: In C++, classes are defined using the class keyword, and objects are created similarly to Java using the new keyword followed by the class constructor. Attributes and methods are defined within the class, and access specifiers like public, private, or protected are used to control access.
class Car {
private:
std::string make;
std::string model;
public:
Car(std::string make, std::string model) {
this->make = make;
this->model = model;
}
void displayInfo() {
std::cout << “Make: ” << make << “, Model: ” << model << std::endl;
}
};
Car car1(“Toyota”, “Corolla”);
car1.displayInfo();
- Inheritance:
Python: In Python, inheritance is specified by listing the base class(es) in parentheses after the derived class name.
class ElectricCar(Car):
def __init__(self, make, model, battery_capacity):
super().__init__(make, model)
self.battery_capacity = battery_capacity
Java: In Java, inheritance is specified using the extends keyword followed by the superclass name.
public class ElectricCar extends Car {
private int batteryCapacity;
public ElectricCar(String make, String model, int batteryCapacity) {
super(make, model);
this.batteryCapacity = batteryCapacity;
}
}
C++: In C++, inheritance is specified using the : operator followed by the access specifier and the base class name.
class ElectricCar : public Car {
private:
int batteryCapacity;
public:
ElectricCar(std::string make, std::string model, int batteryCapacity)
: Car(make, model), batteryCapacity(batteryCapacity) {}
};
- Encapsulation:
Python: In Python, encapsulation is achieved using naming conventions such as _ (single underscore) and __ (double underscore) to indicate private and protected attributes, respectively.
Java: In Java, encapsulation is enforced using access modifiers like private, protected, and public to control access to class members.
C++: In C++, encapsulation is implemented using access specifiers (private, protected, public) to restrict access to class members.
- Polymorphism:
Python: In Python, polymorphism is achieved implicitly through duck typing and method overloading.
Java: In Java, polymorphism is achieved through method overriding (runtime polymorphism) and method overloading (compile-time polymorphism).
C++: In C++, polymorphism is implemented using virtual functions and function overloading.
- Implementing classes and objects
Introduction:
Classes and objects are fundamental concepts in Object-Oriented Programming (OOP) that allow developers to model real-world entities and their interactions in code. In this lesson, we will explore how to implement classes and create objects in Python, Java, and C++.
- Classes and Objects:
Definition:
A class is a blueprint or template for creating objects. It defines the attributes (data) and methods (functions) that objects of that class will have.
An object is an instance of a class. It represents a specific instance or occurrence of the class.
Implementation:
Python: Classes are defined using the class keyword, and objects are created using the class constructor.
Java: Classes are defined using the class keyword, and objects are created using the new keyword followed by the class constructor.
C++: Classes are defined using the class keyword, and objects are created using the class constructor similarly to Java.
- Defining Attributes and Methods:
Attributes: Attributes are variables that hold data associated with a class or object.
Methods: Methods are functions that define behaviors or actions that objects of the class can perform.
Implementation:
Python:
class Car:
def __init__(self, make, model):
self.make = make
self.model = model
def display_info(self):
print(f”Make: {self.make}, Model: {self.model}”)
car1 = Car(“Toyota”, “Corolla”)
Java:
public class Car {
private String make;
private String model;
public Car(String make, String model) {
this.make = make;
this.model = model;
}
public void displayInfo() {
System.out.println(“Make: ” + make + “, Model: ” + model);
}
}
Car car1 = new Car(“Toyota”, “Corolla”);
C++:
class Car {
private:
std::string make;
std::string model;
public:
Car(std::string make, std::string model) {
this->make = make;
this->model = model;
}
void displayInfo() {
std::cout << “Make: ” << make << “, Model: ” << model << std::endl;
}
};
Car car1(“Toyota”, “Corolla”);
- Instantiating Objects and Invoking Methods:
Instantiation: To create an object of a class, we use the class constructor followed by any required arguments.
Method Invocation: Once an object is created, we can invoke its methods using the dot notation (object.method()).
Implementation:
Python:
car1.display_info()
Java:
car1.displayInfo();
C++:
car1.displayInfo();
- Practice Exercise:
Problem: Create a class Rectangle with attributes length and width, and methods to calculate area and perimeter.
Solution:
Python:
class Rectangle:
def __init__(self, length, width):
self.length = length
self.width = width
def area(self):
return self.length * self.width
def perimeter(self):
return 2 * (self.length + self.width)
rectangle1 = Rectangle(5, 3)
print(“Area:”, rectangle1.area())
print(“Perimeter:”, rectangle1.perimeter())
- Designing and modeling software using OOP
Introduction:
Designing and modeling software using Object-Oriented Programming (OOP) is a systematic approach to structuring code and organizing functionality into classes and objects. By following principles such as encapsulation, inheritance, and polymorphism, developers can create modular, reusable, and maintainable software systems. In this lesson, we will explore how to design and model software using OOP principles.
- Object-Oriented Design (OOD) Principles:
Abstraction: Abstracting away unnecessary details and focusing on essential characteristics to represent real-world entities as classes.
Encapsulation: Bundling data and methods within a class, hiding the internal state and exposing only necessary functionalities through well-defined interfaces.
Inheritance: Establishing a hierarchical relationship between classes to promote code reuse and establish an “is-a” relationship.
Polymorphism: Allowing objects of different classes to be treated as objects of a common superclass, enabling flexibility and extensibility.
- Modeling Software using OOP:
Identify Entities: Identify the key entities or objects in the problem domain that need to be represented in the software system.
Define Classes: Define classes to represent these entities, including attributes to hold data and methods to define behaviors.
Establish Relationships: Establish relationships between classes using associations, aggregations, or compositions to model interactions between objects.
Refine Designs: Refine the initial design by identifying commonalities and variations, applying inheritance to capture shared behaviors and attributes.
Ensure Modularity: Ensure that classes are modular and cohesive, with each class responsible for a specific aspect of the system’s functionality.
- Using UML Diagrams for Visualization:
Class Diagrams: Visualize the structure of classes, including attributes, methods, and relationships between classes.
Sequence Diagrams: Illustrate the flow of interactions between objects over time, depicting the sequence of method calls.
Use Case Diagrams: Identify and describe the interactions between actors (users) and the system, capturing user requirements and system functionality.
- Implementation in Programming Languages:
Python: Implement classes and objects using the class keyword and instantiate objects using constructors.
Java: Define classes using the class keyword, create objects using the new keyword, and use access modifiers for encapsulation.
C++: Declare classes using the class keyword, create objects using constructors, and use access specifiers (private, protected, public) for encapsulation.
- Practice Exercise:
Problem: Design a library management system using OOP principles, including classes for books, patrons, and library branches, and methods to handle book checkout, return, and reservation.
Solution: Define classes for Book, Patron, and LibraryBranch, including attributes for book details, patron information, and methods to handle library operations.