###### tags: Python
# Object Oriented Programming
creat a class like string
new_string = 'hello' --> instanciate
new_string is a object which orientes to the string class.
## 4 Pillars of OOP
### 1. Encapsulation - pack the method or attribute into class
### 2. Abstration - get access to method or attribute without knowing how it codes
### 3. Inheritance - to inherit the class
#### Example
```
class User: - Parent Class
def __init__(self, email):
self.email = email
def sign_in(self):
print("logged in")
class Wizard(User): -Subclass
def __init__(self, name, power, email):
super().__init__(email)
self.name = name
self.power = power
def attack(self):
print(f'attacking with power of {self.power}')
class Archer(User):
def __init__(self, name, num_arrows):
self.name = name
self.num_arrows = num_arrows
def attack(self):
print(f'attacking with arrows: arrows left-{self.num_arrows}')
wizard1 = Wizard('Merlin, 50', merlin@gmail.com)
archer1 = Archer('Robin', 100)
wizard1.attack()
archer1.attack()
```
```
isinstance(instance, Class) - check the instance is involved in Class
isinstance(wizard1, Wizard)
```
#### Multiple inheritance - too complicated, rarely use
```
class HybridBorg(Wizard, Archer):
def __init__(self, name, power, arrows):
Archer.__init__(self, name, arrows)
Wizard.__init__(self, name, power)
hb1 = HybridBorg('borgie', 50, 100)
```
### 4. Polymorphism - share the same method name with different output
#### Example 1
```
class PlayerCharacter
(Upper for the first word)
def __init__(self, name='anonymous', age=0):
self._name = name -> attributes
self._age = age
def speak(self):
print(f'my name is {self.name}, and I am {self.age} years old')
@classmethod
def adding_things(cls, num1, num2):
return num1 + num2
player1 = PlayerCharacter('Tom', 20) - don't have to create a object to use method
@staticmethod
def adding_things(num1, num2):
return num1 + num2 - without adding cls parameter into method
```
## Private and Public Variables
self._name = name --> to note that this is private variable not to overwrite
## Dunder Method - Built-in Method of object
`__init__` (double underscore called Dunder method)
```
calss Toy():
def __init__(self, color, age):
self.color = color
self.age = age
```
def __str__(self):
return f'{self.color}'
```
action_figure = Toy('red', 0)
action_figure.__str__() == str(action_figure)
```
## MRO - Method Resolution Order(不要寫這種邏輯)
class A:
num = 10
class B(A):
pass
class C(A):
num = 1
class D(B, C):
pass
print(D.mro())
```
A
/ \
/ \
B C
\ /
\ /
D
```