This is a guide for developers who want to get a deeper knowledge of Python. You can find Python classes for beginners in this article.
This guide will cover the following:
Inheritance in OOP is the ability of one class to derive other class properties( variables or functions). Inheritance is a very strong concept as it offers reusability of the code as you won’t need to start each code from scratch where you can use the same code and add as many features as your application needs. Also, it allows subclasses from the child class to inherit from the parent class e.g if class Fruit inherits from class Food all the classes that inherit from class Fruit can also inherit from the class Food. You let a class inherit from another by inserting the name of the parent class within brackets() after you define the second class with the following syntax
class Fruit(Food):. Let’s have some basic example for inheritance:
class Food: def __init__(self, name): self.name = name def getName(self): return self.name def isFresh(self): return True class Fruit(Food): def isFresh(self): return False food = Food("Meat") print(food.getName(),food.isFresh()) fruit = Fruit("Apple") print(fruit.getName(),fruit.isFresh())
As you can see, when we applied the mentioned syntax for inheriting the subclass or the child class Fruit has the ability to inherit from the base class or the parent class Food, so it inherited the constructor method for creating the name and the getName method to return the name.
Types of inheritance
Single inheritance gives the ability to a derived class or child class to inherit all the properties of a single parent class. Let’s see an example:
class Food: def isFresh(self): print("Yes it's fresh") class Fruit(Food): def weight(self): print("Weight is 10 kilos") fruit = Fruit() fruit.isFresh() fruit.weight()
Yes it's fresh
Weight is 10 kilos
In this type of inheritance, the class Fruit has inherited the method in the class food and reused it when an object of the class Fruit was created.
In this type of inheritance, the child class has the ability to inherit from various parent classes. Using the following syntax
class child(parentclass1,parentclass2), the child class can inherit the properties of both parentclass1&2 and more depending on your application. Let’s see an example:
class Food: def isFresh(self): print("Yes,it's fresh") class Menu: def isAvailable(self): print("Yes,it's available") class Fruit(Food,Menu): pass fruit = Fruit() fruit.isFresh() fruit.isAvailable()
Yes, it's fresh
Yes, it's available
You can see the child class Fruit inherited both the methods found in the parent classes Food & Menu.
In this type of inheritance, the child class has another child class that inherits from it and in this case, you can call it a grandchild class or call the base class grandparent. It’s the same as the relationship between a son and his grandfather. In this case, the child class can inherit from both parent and grandparent classes. Let’s see an example:
class Family: family_name = "" class Middle(Family): middle_name = "" class Name(Middle): name = "" def fullName(self): print(self.name, self.middle_name,self.family_name) myname = Name() myname.family_name = "Patrick" myname.middle_name = "Robert" myname.name = "John" myname.fullName()
John Robert Patrick
As you can see the class Middle inherits from the class Family so it has access to its properties and as the class Name inherits from the class Middle then by order it inherits from the class Family also. As we can see it has accessed the variable family_name from the grandparent class.
In this type of inheritance, one parent or base class has more than one child class inheriting from it where they all can inherit all the properties of the parent class. Let’s see an example:
class Fruit: def approve(self): print("Yes, it belongs to Fruit class") class Apple(Fruit): def anApple(self): print("yes, it also belongs to Apple class") class Orange(Fruit): def anOrange(self): print("yes, it also belongs to Orange class") apple = Apple() orange = Orange() apple.approve() apple.anApple() orange.approve() orange.anOrange()
Yes, it belongs to Fruit class
yes, it also belongs to Apple class
Yes, it belongs to Fruit class
yes, it also belongs to Orange class
In this type of inheritance besides each class’s own functions, we can see that classes Apple & Orange also inherited the class Fruit and had access to the functions presented in it.
Polymorphism means having many forms or states of the same thing. So in programming polymorphism means having the same function name but are used differently and you can see this in Python for example with the function
len() where it can be used with strings, arrays, and a lot of other concepts. That’s the concept of polymorphism where we can reuse the name of the function but with different usage and output and that can be applied in classes as well with all its concepts.
Polymorphism with class functions
As many classes as you have some of these classes can have the same function names but with different outputs, each function gives its unique output when an instance of its class is made now the program knows that you are calling this function of that class. Let’s see an example:
class Orange: def color(self): print("it's color is orange") def weight(self): print("it weighs 200 grams") class Apple: def color(self): print("it's color is red") def weight(self): print("it weighs 250 grams") orange = Orange() apple = Apple() orange.color() orange.weight() apple.color() apple.weight()
it's color is orange
it weighs 200 grams
it's color is red
it weighs 250 grams
As you can see that both classes Orange and Apple have the same function names color & weight. But as Python supports Polymorphism it distinguishes between each of them and what output they give based on whether they called on which instance either of the Orange class instance or Apple class instance.
Polymorphism with inherited functions
Also, polymorphism concept can be applied to inherited functions although the child class inherited the functions presented in the parent class, polymorphism allows you to define functions with the same name of the functions presented in the parent class and modify it and that is called Function Overriding. And that helps us with modifying some inherited functions that might need changes to fit the child class. Let’s see an example:
class Fruit: def color(self): print("Most fruits have a green color") class Orange: def color(self): print("but Orange has orange color") class Apple: def color(self): print("and Apple has red color") fruit = Fruit() orange = Orange() apple = Apple() fruit.color() orange.color() apple.color()
Most fruits have a green color
but Orange has orange color
and Apple has red color
Applying polymorphism in the above code lets you fit the inherited function in the way you want for both of the child classes where Function Overriding took a place when the inherited function was defined again within reach of the child classes. So you can see when an instance is created of the Orange & Apple classes each
color() function gives an output depending on which instance it’s called at.
Encapsulation is one of the main concepts of OOP where it helps you to keep your data safe from any modifications or changes. So it’s like you created an object of a class Encapsulations allows you to modify variables of that object only using functions presented in that object too.
Types of members
These members shouldn’t be accessed from outside the class however nothing can stop you from doing that, also they can be accessed from the class itself or any of its subclasses. But Python doesn’t have a Protected keyword however this can still be achieved by putting an underscore before the member like this
_a, this is now a protected member. Let’s see an example:
class Fruit: #name as a public member name = "Banana" #name as a protected member _name = "Orange" class Orange(Fruit): pass orange = Orange() print(orange.name) print(orange._name)
As you can see both public members and protected members can be directly accessed within a subclass or a child class of the base class they are defined at.
These types of members are like the protected ones but they cannot be defined outside the class and they cannot even get access through the subclasses from the base class they are defined within. Also, Python doesn’t have the private keyword but still, this can be applied by adding two underscores before the member name like this
__a. Let’s see if we tried to access a private member outside the class:
class Fruit: #name as a public member name = "Banana" #name as a protected member _name = "Orange" #name as a private member __name = "Apple" fruit = Fruit() print(fruit.name) print(fruit._name) print(fruit.__name)
AttributeError: ‘Fruit’ object has no attribute ‘__name’
Here we can see the difference between protected and private members, although protected members shouldn’t be accessed from outside the class it’s doable. Unlikely with the private members they are forbidden to get accessed from outside the class.
Setters and getters
But you still have the ability to modify and access private members using getters and setters where it’s an indirect way to access private members where this is done within the class itself and the user only deals with setters and getters outside the class. And that is the ideal definition of Encapsulation where the data members of the class are only accessed using functions of the class and that takes place inside the class ONLY. Let’s see an example:
class Fruit: def __init__(self): self.__type = "Banana" def setType(self,type): self.__type = type def getType(self): print(self.__type) fruit = Fruit() fruit.getType() fruit.setType("Orange") fruit.getType()
You can see that the modifications and the printing of the private member are done through setType & getType functions.