# Object Oriented Programming Continued
> Python Intermediate Course by @ivorchu
Class Method & Static Method
---
| Method Type | Characteristic |
| -------- | -------- |
| Class Method | Has the access to the states or values of the class |
| Static Method | Can not access or modify class state |
**Class Method**
* Bound to the class but not the object of the class
* Have access to the state of the class, so it will take a class parameter that points to the class
* It can modify a class state that would apply across all the instances of the class. For example it can modify a class variable that will be applicable to all the instances.
***
* A class method receives the class as implicit first argument, just like an instance method receives the instance
* cls: a conserved variable that indicates the name of the class --> Just like the keyword "self" used in the initialize function__init__(self)
***
##### Syntax
```
class C(object):
@classmethod
def fun(cls, arg1, arg2, ...):
....
fun: function that needs to be converted into a class method
returns: a class method for function.
```
**Static Method**
* Also bound to the class but not the object of the class
* Can not access or modify the class state
* A direct method that is included in the class
***
* A static method does not receive an implicit first argument.
***
##### Syntax
```
class C(object):
@staticmethod
def fun(arg1, arg2, ...):
...
returns: a static method for function fun.
```
**Class Method v.s. Static Method**
* A class method takes cls as first parameter while a static method needs no specific parameters.
* A class method can access or modify class state while a static method can’t access or modify it.
* In general, static methods know nothing about class state. They are utility type methods that take some parameters and work upon those parameters. On the other hand class methods must have class as parameter.
* We use @classmethod decorator in python to create a class method and we use @staticmethod decorator to create a static method in python.
> Think of this way, class methods are used when you are dealing with classes and objects, while static methods are used when you are declaring a plain function that does a specific job.
**Example**
##### Implemetation
```
class Dog:
dogs = [] # An array that saves all Dog objects
def __init__(self, name):
self.name = name
self.dogs.append(self) # Append current Dog object to the array
@classmethod
def num_dogs(cls): # Automatically gives a cls argument
# Which indicates the class itself
return len(cls.dogs) # Return the length of the array
@staticmethod
def bark(n):
for i in range(n): # Print n times "Bark!"
print("Bark!")
```
##### Output
```
>>> a = Dog("Bob")
>>> a.num_dogs()
1
>>> b = Dog("Tom")
>>> b.num_dogs()
2
>>> Dog.bark(3)
Bark!
Bark!
Bark!
```
> Note the difference between self and cls:
> self -> the object created
> cls -> the class itself
****
Public, Protected & Private Classes
---
| Access | Authentication |
| -------- | -------- |
| Public | Can be accessed by any authentication |
| Private | Can only be accessed by itself and its sub-class |
| Protected | Can only be accessed by itself |
> Heres a story for you to see the difference:
> This is a story about Tim. Tim has 10 dollars in his pocket (private). One day Tim's dad gone mad and started to splash out money on the street (public). Unfortunately, Tim's dad was hit by a car and Tim recovers the remaining money in his dad's pocket (Protected).
##### syntax
```
class Money # Declaing a private class
class _Money # Declaring a protected class
class __Money # Declaring a private class
```
> Same method can be used on variables and functions
```
apple = 1 # public
_banana = 1 # protected
__orange = 1 #private
def apple() # public
def _banana() # protected
def __orange() #private
```
***
**Example**
#### **Public**
##### Implementation
```
class employee:
def __init__(self, name, sal):
self.name = name
self.salary = sal
```
##### Output
```
>>> e1 = employee("Bob", 10000)
>>> e1.salary
10000
>>> e1.salary = 20000
>>> e1.salary
20000
```
***
#### **Protected**
##### Implementation
```
class employee:
def __init__(self, name, sal):
self._name = name
self._salary = sal
```
##### Output
```
>>> e1 = employee("Bob", 10000)
>>> e1._salary
10000
>>> e1._salary = 20000
>>> e1._salary
20000
```
***
### **Private**
##### Implementation
```
class employee:
def __init__(self, name, sal):
self.__name = name
self.__salary = sal
```
##### Output
```
>>> e1 = employee("Bob", 10000)
>>> e1.__salary
Traceback (most recent call last):
File "<pyshell#6>", line 1, in <module>
e1.__salary
AttributeError: 'employee' object has no attribute '__salary'
>>> e1._employee__salary
10000
>>> e1._employee__salary = 20000
>>> e1._employee__salary
20000
```
> Note theres an error occured:
> Python would automatically change private variables into _object._class__variable so it can’t be accessed from the outside, this is where user’s authentication takes place
---
Reference:
https://www.geeksforgeeks.org/