#A parent/super class
class Animal:
#__init__ = 'Dunder method', it must always have the argument 'self'
def __init__(self,legs,prey):
#Attributes
#Protected attribute
self._legs = legs
#Private attribute
self.__prey = prey
#Methods.Difference between methods and functions are..
#That a function can be called independently
#But a method cannot be called if a class has not been made
#They are also called using dot notation
def sound(self):
print('Generic sound')
#INHERITANCE
#Below is a subclass(or child class)
class Dog(Animal):
#A subclass 'inherits' the attributes/methods of its parent class, and can add its own unique attributes/methods
def __init__(self,legs,prey,breed):
#Use the 'super().__init__' method to inherit the same attributes as in the parent class
super().__init__(legs,prey)
#Unique attribute
self.breed = breed
#Class method, A type of method where the class itself is called, so you dont need to create an object to call it
@classmethod
#As you can see its a decorator, so its called the same way decorators are
#Below is an example of 'Method overriding'
#The same method from the supercalss is used but altered and therefore completely overriden
#Method overriding is an example of Polymorphism
def sound(cls):
print('Woof')
#Another type of method is staticmethod, its also a decorator so its called using @staticmethod before the method itself
#One difference between class method and a static methoed is that static method doesnt need the additional arguments like a class method('cls')
#Another difference is that a staticmethod doesnt modify or access the attributes of a class
#And unlike a regular method it can be called even though no object has been created
#This is an object
wild_dog = Dog(4,'rabbit','Pug')
#You can access the objects attributes as such
print(wild_dog._legs)
#Since 'prey' is a private attribute, it cannot be accessed outside a class unless you use 'name mangling'
print(wild_dog._Animal__prey)
#Notice how you dont need to call the objects name when using a class method
Dog.sound()