Apart from the relative conceptual simplicity of Object-oriented programming over traditional programming methodologies, OOP also provides a number of technical techniques which enhances the reusability of the code we write, and allows for functionality we would find very difficult to replicate in structured programming. One such technique is that of Inheritance.
Inheritance is the ability to create an object of a class which "inherits" attributes and functions of another class. This allows us to define generic "parent" classes, whose functionality can then be extended and specialized by "children" classes which inherit from the parent.
For example, suppose we are writing software for the real estate industry. We might create a generalized parent class that looks like this:
PROPERTY ----------------------- property_id name description address owner_name owner_telephone owner_email selling_price surface_area status ----------------------- print_advert() mark_sold() mark_available()
However, we might want specific data to be stored for specific types of property, and thus we might then create child classes such as: apartment, house, duplex, farm, etc... As a further example of what one of these child classes might look at, let's consider the farm child class:
FARM (extends PROPERTY) ----------------------- plot_number land_area farm_type num_employees num_buildings has_dam has_stables has_greenhouse has_orchard -----------------------
In this example, the farm class, as with the other child classes, will be made up of the attributes and functions of the parent class, as well as the additional attributes and functions of the child class.
Inheritance in Python
The following syntax is used in Python to create a child class which inherits from a parent class:
class ChildClass(ParentClass): # Class Definition goes here
So we see here that following the class name, we have the parent class name in brackets.
Note: Python allows multiple inheritance, where you can provide a comma-separated list of parent classes to inherit from. However, please be very careful when doing this, and if you find yourself in a situation where you are about to use multiple inheritance, ask yourself why it is necessary, as you have likely made a design mistake.
Now that we have seen the syntax, let's take a look at a code example:
class Property: property_id = 0 name = "" description = "" address = "" owner_name = "" owner_telephone = "" owner_email = "" selling_price = "" surface_area = "" status = "" def __init__(self): self.property_id = 1 def print_advert(self): if self.status == "Available": print "Property: P-%d - %s for $%d" % (self.property_id, self.name, self.selling_price) print self.description print "Surface Area: %s" % (self.surface_area) print "Owner: %s (%s)" % (self.owner_name, self.owner_telephone) print "Contact the owner at %s" % (self.owner_email) else: print "Sold!" def mark_sold(self): self.status = "Sold" def mark_available(self): self.status = "Available" class Farm(Property): plot_number = "" land_area = 0 farm_type = "" num_employees = 0 num_buildings = 0 has_dam = False has_stables = False has_greenhouse = False has_orchard = False # Create Farm my_farm = Farm() my_farm.property_id = 1 my_farm.name = "Dairy Queen Farm" my_farm.description = "A family-run dairy farm with a friendly staff and well cared for cows" my_farm.selling_price = 1200000 my_farm.surface_area = "20 acres" my_farm.owner_name = "Henry Ford" my_farm.owner_telephone = "123456789" my_farm.owner_email = "email@example.com" # Set as Available my_farm.mark_available() # Display Advert my_farm.print_advert()
In the above code, we create our parent class, Property, and extended it with our specialized Farm child class. We then create a Farm object my_farm and set attributes for the object, and then call the print_advert() function the child class inherited from the parent class.
Accessing Parent attributes and functions
If you need to directly access attributes or functions of the parent class, you can make use of the super() function. This access the "super" class of a child class. The syntax is as follows:
class B(A): def method(self, arg): super(B, self).method(arg)
Note: Although this is technically viable, it is not recommended to use this technique, as it leads to poorly defined classes.
Within classes, certain attributes and functions may be restricted in terms of which other areas of code are able to access them. For example, you might want an attribute of a class to only be accessible from within that class, as it is used for some internal purpose, and not meant for use outside of that class. Or, you might want an attribute or function to only be accessible within a class and its parent/child class. In these situations, we specify the visibility of the attribute or function.
Types of Visibility
There are three types of visibility:
- Public: The attribute or function are accessible from inside as well as outside of the class/object.
- Private: The attribute or function are only accessible within the class in which it is defined.
- Protected: The attribute or function are accessible between classes involved in inheritance, but not outside of that.
Write a program which defines a parent company class with a function print_summary() which outputs " | | ", and two children classes: Supplier and Client. Populate one array with Suppliers, and one array with Clients, then loop through each array calling the print_summary() function so you effectively print out a phonebook of clients and suppliers ordered by those groupings.