# Modular Programming ## 1. Introduction - A. What is Object-Oriented Programming? - B. Why use OOP? (vs. procedural) - C. Real-world analogies (e.g., modeling components like pumps, motors, or vehicles) ## 2. Core OOP Concepts - A. **Classes and Objects** - Definitions - Syntax in Python - B. **Attributes and Methods** - Instance variables - Functions inside classes - C. **Encapsulation** - Public vs private variables - Using `__init__` and `self` - D. **Inheritance** - Parent and child classes - Reuse and extension of code - E. **Polymorphism** _(brief overview)_ - Method overriding - Flexibility in interfaces ## 3. Python OOP Syntax and Examples - A. Define a simple class (e.g., `Spring`) - B. Instantiate objects and use methods - C. Show `__init__`, `__str__`, custom methods - D. Add a derived class (e.g., `DampedSpring` inherits from `Spring`) ## 4. Engineering Applications of OOP - A. Modeling a mechanical system using classes - Example: Mass-Spring-Damper system - B. Creating reusable components (e.g., `Material`, `Beam`, `Force`) - C. Organizing simulation code with OOP ## 5. Hands-On Coding Activity - A. Write a class for a basic physical component (e.g., `Motor`) - B. Add behavior (e.g., `calculate_torque`) - C. Extend with inheritance (e.g., `ServoMotor`) - D. Bonus: Integrate two objects to simulate interaction --- # Modular Programming OOP What is it? Modular programming or better known as Object-Oriented Programming (OOP) is a way we can structure programs so that properties and behaviors of objects are grouped together. It allows us to re-use code which simplifies the code for better readability in larger programs and reduces the potential for bugs. You're probably familiar with the saying "Don't re-invent the wheel". OOP is the programmers solution to this. Python allows us to import libraries so that we don't have to write everything from scratch. The libraries used in this course provide us with algorithms to calculate a solution, structure data and plot data. When looking at the source code of these library you may see keywords, such as `class`. This tutorial will delve into the fundamental concepts of OOP. One analogy for OOP goes as follows. If we were to build a house we need to follow a common structure or blueprint which defines what a house should have, this is the *class*. The class may be thought of as the blueprint for a house, defining what a house should include (rooms, doors and windows). Then we have *objects* which is the actual house that is built from the blueprint. You can build multiple objects from the same plan. Imagine you are an urban planner in the town of Wellington, the town is rapidly expanding and housing is in high demand. You are tasked with developing a new housing area. Designing 50 different houses will take too much, but building the same house 50 times will make the neighborhood look like a subdivision from the 1950s. Class: Is the blueprint of the house Object: Is a specific house in the neighborhood with defined attributes Method: Attached garage Let's take a look at an example. Do not worry if you don't understand the syntax below, we will explain this later. Let's define the class: ```python class People(): def __init__(self, name, age): self.name = name self.age = age def greet(self): print("Greetings, " + self.name) ``` Now we can use our class to define new objects: ```python person1 = People(name = 'Iron Man', age = 35) person1.greet() print(person1.name,person1.age) person2 = People(name = 'Batman', age = 33) person2.greet() print(person2.name,person2.age) ``` In the example above we first defined the class `People` with `name` and `age` as the data and the `greet` as the method. Once we initialized an object `person1` we can see that the class defines the entire structure, whilst the object is just an instance of the class. It is clear that `person1` and `person2` are independent with each other, though they are all instantiated from the same class. 3. Why use it? You may wonder why you should even bother with classes and object. Why not store data as arrays? ```python kirk = ["James Kirk", 34, "Captain", 2265] spock = ["Spock", 35, "Science Officer", 2254] mccoy = ["Leonard McCoy", "Chief Medical Officer", 2266] ``` 1. Simplifies the code for better readability. 2. reduces the number of potential bugs. 4. Real world uses 1. Python Libraries/Packages 2. Core concepts 1. Class (Blueprints) A class is used to define logical grouping of data and functions and objects. 2. Objects () 3. Attributes 4. Methods - A **method** is a **function that lives inside a class** and has access to the data stored inside the object. 5. The four pillars: 1. Encapsulation 2. Inheritance 3. Abstraction 4. Polymorphism 3. Syntax and Examples ```mermaid flowchart TD A[OOP] --> B[Class] B --> C[Attributes: variables / data] B --> D[Methods: functions / behaviors] C -->|define structure| E[Class Definition] D -->|define behavior| E E -->|instantiation| F[Object] F --> G[Object has its own
attribute values] F --> H[Object can call methods] ``` Starting a class is done with the `class` keyword followed by the name of the class. ```python class Dog: pass ``` In this example `pass` is used a placeholder to indicate where code will eventually go. This prevents python to output any errors. Next, give our class some properties and behaviors. For the purpose of this demonstration we will keep it small but in reality the class may be significantly more detailed. The properties are defined inside the method called `.__init__()`. It runs automatically when a new object of a class is created. It's main purpose is to initialize the object attributes and set up its initial state. When an object is created, memory is allocated for it, and `__init__` helps organize that memory by assigning values to attributes. Let's add a name, breed and age attibute to our ```python class Dog: def __init__(self, name, breed="Mixed", age=1): self.name = name self.breed = breed self.age = age dog1 = Dog("Buddy") dog2 = Dog("Bolt", "German Sheppard", 5) print(dog1.name, dog1.breed, dog1.age) print(dog2.name, dog2.breed, dog2.age) ``` Notice how the `__init__` method defaults the inputs`breed="Mixed"` and `age=1` when no parameters are given. ```python ``` ```python ``` ```python ``` ```python ```