|
1 | 1 | # Lecture 2 |
2 | 2 |
|
3 | 3 | ## Lecture 2 Concepts |
4 | | -- UML (Unified Modelling Language) |
5 | 4 | - Overriding Polymorphism |
6 | 5 | - DRY |
| 6 | +- Encapsulation |
| 7 | +- Setters & Getters |
7 | 8 | - Overloading Polymorphism |
8 | 9 |
|
9 | | -## UML Class Diagrams |
10 | | - |
11 | | -A UML (Unified Modelling Language) class diagram visually describes the structure of a system by showing its classes, their attributes (variables), methods (functions), and relationships (like inheritance). |
12 | | - |
13 | | -```text |
14 | | ----------------------- |
15 | | -| Student | <-- Class Name |
16 | | ----------------------- |
17 | | -| -name: String | <-- Attributes |
18 | | -| -age: int | |
19 | | ----------------------- |
20 | | -| +getName(): String | <-- Methods |
21 | | -| +setAge(int): void | |
22 | | ----------------------- |
23 | | -``` |
24 | | - |
25 | | -### Mermaid Markdown UML Class Diagram Example |
26 | | -Below is a Mermaid class diagram for a Pi Pico GPIO Pin and a custom Led_Light class that inherits from it. |
27 | | - |
28 | | -```mermaid |
29 | | -classDiagram |
30 | | -
|
31 | | - class Pin { |
32 | | - -pin: int |
33 | | - +__init__(pin: int) |
34 | | - +value() |
35 | | - +high() |
36 | | - +low() |
37 | | - +toggle() |
38 | | - } |
39 | | -
|
40 | | - class Led_Light { |
41 | | - -debug: bool |
42 | | - -pin: int |
43 | | - -flashing: bool |
44 | | - +__init__(pin: int, flashing: bool, debug: bool) |
45 | | - +on() |
46 | | - +off() |
47 | | - +toggle() |
48 | | - } |
49 | | - Pin <|-- Led_Light : inherits |
50 | | -``` |
51 | | - |
52 | | -Explanation: |
53 | | - |
54 | | -1. Class Name (Top Section): This is the uppermost part of the box. It displays the name of the class (e.g., Student, Order, Car). |
55 | | -2. Attributes (Middle Section): This section lists the attributes (or properties/fields) of the class. Each attribute is typically shown with its visibility (+ for public, - for private, # for protected), name, and type. |
56 | | -3. Methods (Bottom Section): This section lists the methods (or operations/functions) that belong to the class. |
57 | | -Each method is shown with its visibility, name, parameters, and return type. |
58 | | -4. Connections (lines and arrows): These lines and arrows represent relationships (such as inheritance, association, aggregation, and composition) between class boxes. |
59 | | - |
60 | 10 | ## Overriding Polymorphism |
61 | 11 |
|
62 | 12 | **Polymorphism means “many forms.”** |
63 | 13 |
|
64 | 14 | Polymorphism Overriding occurs when a child class (subclass) provides a new implementation for a method it inherits from its parent class (superclass). |
65 | 15 |
|
66 | | -The method in the child class has the same name and parameters as the one in the parent class. When the method is called on an object of the child class, Python (or any object-oriented language) uses the child’s version—even if the object is referenced using the parent type. |
| 16 | +The method in the child class has the same name and parameters as the one in the parent class. When the method is called on an object of the child class, Python (or any object-oriented language) uses the child’s version, even if the object is referenced using the parent type. |
67 | 17 |
|
68 | 18 | ```python |
69 | 19 | from machine import Pin |
@@ -107,6 +57,7 @@ while True: |
107 | 57 | ``` |
108 | 58 |
|
109 | 59 | ## DRY |
| 60 | + |
110 | 61 | The DRY pattern stands for "**Don't Repeat Yourself**"; it is a fundamental principle of programming aimed at reducing repetition of code and logic. This is to avoid duplicating code, logic, or data. |
111 | 62 |
|
112 | 63 | ### Why Use DRY? |
@@ -160,6 +111,59 @@ The DRY pattern stands for "**Don't Repeat Yourself**"; it is a fundamental prin |
160 | 111 | self.off() |
161 | 112 |
|
162 | 113 | ``` |
| 114 | +## Encapsulation |
| 115 | +Encapsulation restricts direct access to some of an object's components (such as attributes or methods), meaning the internal representation of the object is hidden from the outside. This is typically achieved by making certain attributes or methods private (i.e., inaccessible from outside the class) and providing public methods (such as getters and setters) to access or modify those private members. |
| 116 | + |
| 117 | +### Benefits of Encapsulation: |
| 118 | + |
| 119 | +- Data Hiding: Internal object details are hidden, exposing only what is necessary. |
| 120 | +- Improved Security: Prevents external code from directly modifying internal state in unexpected ways. |
| 121 | +- Modularity: Each object manages its own state and behaviour, making code more modular and easier to maintain. |
| 122 | +- Flexibility: Implementation can change without affecting code that uses the object, as long as the public interface remains the same. |
| 123 | + |
| 124 | +```python |
| 125 | +while True: |
| 126 | + print(red_light.led_light_state) # Allowed |
| 127 | + red_light.led_light_state = 1 # Allowed |
| 128 | + print(f"Not allowed: {red_light.__pin} ???") # Not allowed, should raise AttributeError |
| 129 | +``` |
| 130 | + |
| 131 | +> [!Note] |
| 132 | +> In Python, identifiers (variable or method names) that start with double underscores (e.g., `__my_var`) are not truly private in the sense of other languages like C# or C++. Instead, Python uses a mechanism called name mangling. When you define a variable with double underscores, Python changes its name internally to `_ClassName__my_var`. This means it is harder (but not impossible) to access it from outside the class. |
| 133 | +
|
| 134 | +## Setters & Getters |
| 135 | + |
| 136 | +Setters and getters are special methods used in object-oriented programming to access (get) or modify (set) the values of private or protected attributes of a class. They help encapsulate the internal state of an object, providing controlled access. |
| 137 | + |
| 138 | +### Getter |
| 139 | + |
| 140 | +- A getter is a method that retrieves (gets) the value of a private attribute. |
| 141 | +- It allows you to read the value without providing direct access to the underlying variable. |
| 142 | + |
| 143 | +### Setter |
| 144 | + |
| 145 | +- A setter is a method that sets (updates) the value of a private attribute. |
| 146 | +- It allows you to validate or restrict changes before updating the attribute. |
| 147 | + |
| 148 | +```python |
| 149 | + @property |
| 150 | + def led_light_state(self): |
| 151 | + # method overloading polymorphism in this class |
| 152 | + return self.value() |
| 153 | + |
| 154 | + @led_light_state.setter |
| 155 | + def led_light_state(self, value): |
| 156 | + # method overloading polymorphism in this class |
| 157 | + if value == 1: |
| 158 | + self.off() |
| 159 | + elif value == 0: |
| 160 | + self.on() |
| 161 | +``` |
| 162 | + |
| 163 | +### Why Use Setters & Getters |
| 164 | +- Encapsulation: Protects the internal state of the object. |
| 165 | +- Validation: Allows you to add checks before changing values. |
| 166 | +- Abstraction: Hides implementation details from users of the class. |
163 | 167 |
|
164 | 168 | ## Overloading Polymorphism |
165 | 169 |
|
|
0 commit comments