|
10 | 10 | "- in programming, duplicate code is considered evil\n", |
11 | 11 | " - difficult to debug and maintain code\n", |
12 | 12 | "- there are many ways to merge pieces of code or objects that have similar functions\n", |
13 | | - "- the concept of inheritance introduced earlier is an important one that allows us to create **is-a** relationship between two or more classes\n", |
14 | | - " - inherit common code from base/superclass and extend it with specific details in each subclass" |
| 13 | + "- the concept of inheritance allows us to create **is-a** relationship between two or more classes\n", |
| 14 | + " - inherit common code from base/superclass and extend/override it with specific details in each subclass (aka Polymorphism)" |
15 | 15 | ] |
16 | 16 | }, |
17 | 17 | { |
|
23 | 23 | "\n", |
24 | 24 | "- technically every class inherits from the built-in *object* class\n", |
25 | 25 | "- generally, we extend the base/parent/super class and customize/add more functionalities to the derived/child class\n", |
26 | | - "- child class inherits methods and attributes defined in parent classes" |
| 26 | + "- child class inherits methods and attributes defined in parent classes\n", |
| 27 | + "\n", |
| 28 | + "" |
27 | 29 | ] |
28 | 30 | }, |
29 | 31 | { |
|
160 | 162 | "metadata": {}, |
161 | 163 | "outputs": [], |
162 | 164 | "source": [ |
163 | | - "# each object all has access to class variable\n", |
164 | | - "# not common notation\n", |
| 165 | + "# each object has access to class variable\n", |
| 166 | + "# not common notation; confusing as if all_contacts is an instance variable\n", |
165 | 167 | "pprint(c.all_contacts)" |
166 | 168 | ] |
167 | 169 | }, |
|
172 | 174 | "metadata": {}, |
173 | 175 | "outputs": [], |
174 | 176 | "source": [ |
| 177 | + "# better notation\n", |
175 | 178 | "pprint(Contact.all_contacts)" |
176 | 179 | ] |
177 | 180 | }, |
|
1047 | 1050 | }, |
1048 | 1051 | { |
1049 | 1052 | "cell_type": "code", |
1050 | | - "execution_count": 161, |
| 1053 | + "execution_count": 6, |
1051 | 1054 | "id": "cb72de1f", |
1052 | 1055 | "metadata": {}, |
1053 | 1056 | "outputs": [], |
|
1083 | 1086 | }, |
1084 | 1087 | { |
1085 | 1088 | "cell_type": "code", |
1086 | | - "execution_count": 162, |
| 1089 | + "execution_count": 7, |
1087 | 1090 | "id": "652387cb", |
1088 | 1091 | "metadata": {}, |
1089 | 1092 | "outputs": [ |
|
1107 | 1110 | }, |
1108 | 1111 | { |
1109 | 1112 | "cell_type": "code", |
1110 | | - "execution_count": 163, |
| 1113 | + "execution_count": 8, |
1111 | 1114 | "id": "86ef7003", |
1112 | 1115 | "metadata": {}, |
1113 | 1116 | "outputs": [ |
|
1138 | 1141 | }, |
1139 | 1142 | { |
1140 | 1143 | "cell_type": "code", |
1141 | | - "execution_count": 164, |
| 1144 | + "execution_count": 9, |
1142 | 1145 | "id": "8be64c14", |
1143 | 1146 | "metadata": {}, |
1144 | 1147 | "outputs": [], |
|
1173 | 1176 | }, |
1174 | 1177 | { |
1175 | 1178 | "cell_type": "code", |
1176 | | - "execution_count": 165, |
| 1179 | + "execution_count": 10, |
1177 | 1180 | "id": "ee517faa", |
1178 | 1181 | "metadata": {}, |
1179 | 1182 | "outputs": [ |
|
1195 | 1198 | }, |
1196 | 1199 | { |
1197 | 1200 | "cell_type": "code", |
1198 | | - "execution_count": 166, |
| 1201 | + "execution_count": 11, |
1199 | 1202 | "id": "74dce83f", |
1200 | 1203 | "metadata": {}, |
1201 | 1204 | "outputs": [ |
|
1226 | 1229 | }, |
1227 | 1230 | { |
1228 | 1231 | "cell_type": "code", |
1229 | | - "execution_count": 167, |
| 1232 | + "execution_count": 12, |
1230 | 1233 | "id": "a7271b87", |
1231 | 1234 | "metadata": {}, |
1232 | 1235 | "outputs": [], |
|
1236 | 1239 | }, |
1237 | 1240 | { |
1238 | 1241 | "cell_type": "code", |
1239 | | - "execution_count": 168, |
| 1242 | + "execution_count": 13, |
1240 | 1243 | "id": "d1381eba", |
1241 | 1244 | "metadata": {}, |
1242 | 1245 | "outputs": [ |
|
1258 | 1261 | }, |
1259 | 1262 | { |
1260 | 1263 | "cell_type": "code", |
1261 | | - "execution_count": null, |
| 1264 | + "execution_count": 14, |
1262 | 1265 | "id": "98b3a4c6", |
1263 | 1266 | "metadata": {}, |
1264 | | - "outputs": [], |
| 1267 | + "outputs": [ |
| 1268 | + { |
| 1269 | + "name": "stdout", |
| 1270 | + "output_type": "stream", |
| 1271 | + "text": [ |
| 1272 | + "(<class '__main__.Subclass_S'>,\n", |
| 1273 | + " <class '__main__.RightSubclass_S'>,\n", |
| 1274 | + " <class '__main__.LeftSubclass_S'>,\n", |
| 1275 | + " <class '__main__.BaseClass_S'>,\n", |
| 1276 | + " <class 'object'>)\n" |
| 1277 | + ] |
| 1278 | + } |
| 1279 | + ], |
1265 | 1280 | "source": [ |
1266 | 1281 | "pprint(Subclass_S.__mro__)" |
1267 | 1282 | ] |
|
1457 | 1472 | "- duck-test: \"If it walks like a duck and it quacks like a duck, then it must be a duck\"\n", |
1458 | 1473 | "- to determine whether a function can be applied to a new type, we apply Python's fundamental rule of polymorphism, called duck typing rule: if all of the operations inside the function can be applied to the type, the function can be applied to the type\n", |
1459 | 1474 | "- it allows us to use *any* object that provides the required behavior without forcing it to be a subclass\n", |
1460 | | - "- `FlacFile` doesn't inherit from AudioFile but it can be interacted with within Python using the exact same interface!" |
| 1475 | + "- `FlacFile` doesn't inherit from AudioFile but it can be interacted with using the exact same interface!" |
1461 | 1476 | ] |
1462 | 1477 | }, |
1463 | 1478 | { |
|
1506 | 1521 | "## Mixin Design Pattern\n", |
1507 | 1522 | "\n", |
1508 | 1523 | "- **Mixin** is the simplest and most useful form of multiple inheritance\n", |
1509 | | - "- a mixin class definition is not intended to exist on its own but is meant to be inherited by some other class\n", |
| 1524 | + "- a mixin class is not meant to be instantiated, but is meant to be inherited by some other class\n", |
| 1525 | + " - it is mixed in with other classes to extend their behavior\n", |
1510 | 1526 | "- the goal is to extend and provide extra functionality without worrying about the correctness of \"is-a\" relationship\n", |
1511 | 1527 | "- mixins are sometimes described as being \"including\" or \"using\" rather than \"inheriting\"\n", |
1512 | 1528 | "- mixins encourage code reuse and can be used to avoid the inheritance ambiguity that multiple inheritance can cause (**diamond problem**)\n", |
|
1516 | 1532 | "- Employee and Address are NOT AsDictionaryMixin, but both of them \"use\" AsDictionaryMixin mixin" |
1517 | 1533 | ] |
1518 | 1534 | }, |
| 1535 | + { |
| 1536 | + "cell_type": "code", |
| 1537 | + "execution_count": 15, |
| 1538 | + "id": "e8107f89", |
| 1539 | + "metadata": {}, |
| 1540 | + "outputs": [ |
| 1541 | + { |
| 1542 | + "name": "stdout", |
| 1543 | + "output_type": "stream", |
| 1544 | + "text": [ |
| 1545 | + "[LOG]: Dog is barking\n", |
| 1546 | + "Woof!\n" |
| 1547 | + ] |
| 1548 | + } |
| 1549 | + ], |
| 1550 | + "source": [ |
| 1551 | + "# Define a Mixin\n", |
| 1552 | + "class LoggingMixin:\n", |
| 1553 | + " def log(self, message):\n", |
| 1554 | + " print(f\"[LOG]: {message}\")\n", |
| 1555 | + "\n", |
| 1556 | + "# Define a Base Class\n", |
| 1557 | + "class Animal:\n", |
| 1558 | + " def speak(self):\n", |
| 1559 | + " pass\n", |
| 1560 | + "\n", |
| 1561 | + "# Use the Mixin\n", |
| 1562 | + "class Dog(Animal, LoggingMixin):\n", |
| 1563 | + " def speak(self):\n", |
| 1564 | + " self.log(\"Dog is barking\")\n", |
| 1565 | + " return \"Woof!\"\n", |
| 1566 | + "\n", |
| 1567 | + "# Usage\n", |
| 1568 | + "dog = Dog()\n", |
| 1569 | + "print(dog.speak()) # Output: [LOG]: Dog is barking \\n Woof!" |
| 1570 | + ] |
| 1571 | + }, |
1519 | 1572 | { |
1520 | 1573 | "cell_type": "code", |
1521 | 1574 | "execution_count": 180, |
|
1775 | 1828 | "### L: Liskov Substitution\n", |
1776 | 1829 | "- named after Barbara Liskov creator of CLU programming language\n", |
1777 | 1830 | "- any subclass can be substituted for its superclass\n", |
| 1831 | + " - any code that uses superclass can be replaced with it's subclass without breaking any code!\n", |
| 1832 | + " - the inverse is not true!\n", |
1778 | 1833 | "- the essence of polymorphism\n", |
1779 | 1834 | "\n", |
1780 | 1835 | "### I: Interface Segregation\n", |
|
1796 | 1851 | "- \"You wanted a banana but what you got was a gorilla holding the banana and the entire jungle\" - Joe Armstrong\n", |
1797 | 1852 | "- inheritance is a powerful tool but it can be misused\n", |
1798 | 1853 | "- alternatives may be better to avoid the inheritance tax:\n", |
1799 | | - " - interfaes and protocols\n", |
| 1854 | + " - interfaces and protocols\n", |
1800 | 1855 | " - delegation\n", |
1801 | | - " - mixins and traits\n", |
1802 | | - "- interfaces and protocols give us prolymorphism without inheritance\n", |
| 1856 | + " - mixins\n", |
| 1857 | + "- interfaces and protocols give us polymorphism without inheritance\n", |
1803 | 1858 | "- delegation is a way to use composition instead of inheritance\n", |
1804 | 1859 | "- delegate to services - Has-A relationship Trumps Is-A relationship\n", |
1805 | 1860 | "- use mixins to share code and functionality\n" |
|
1846 | 1901 | "name": "python", |
1847 | 1902 | "nbconvert_exporter": "python", |
1848 | 1903 | "pygments_lexer": "ipython3", |
1849 | | - "version": "3.10.8" |
| 1904 | + "version": "3.9.13" |
1850 | 1905 | }, |
1851 | 1906 | "vscode": { |
1852 | 1907 | "interpreter": { |
|
0 commit comments