So, inheritance is great for adding new behavior to existing classes, but what about changing behavior? Our Contact class allows only a name and an email address. This may be sufficient for most contacts, but what if we want to add a phone number for our close friends?
As we saw in Chapter 2, Objects in Python, we can do this easily by just setting a phone attribute on the contact after it is constructed. But if we want to make this third variable available on initialization, we have to override __init__. Overriding means altering or replacing a method of the superclass with a new method (with the same name) in the subclass. No special syntax is needed to do this; the subclass's newly created method is automatically called instead of the superclass's method. As shown in the following code:
class Friend(Contact): def __init__(self, name, email, phone): self.name = name self.email = email self.phone = phone
Any method can be overridden, not just __init__. Before we go on, however, we need to address some problems in this example. Our Contact and Friend classes have duplicate code to set up the name and email properties; this can make code maintenance complicated, as we have to update the code in two or more places. More alarmingly, our Friend class is neglecting to add itself to the all_contacts list we have created on the Contact class.
What we really need is a way to execute the original __init__ method on the Contact class from inside our new class. This is what the super function does; it returns the object as an instance of the parent class, allowing us to call the parent method directly:
class Friend(Contact): def __init__(self, name, email, phone): super().__init__(name, email) self.phone = phone
This example first gets the instance of the parent object using super, and calls __init__ on that object, passing in the expected arguments. It then does its own initialization, namely, setting the phone attribute.
A super() call can be made inside any method. Therefore, all methods can be modified via overriding and calls to super. The call to super can also be made at any point in the method; we don't have to make the call as the first line. For example, we may need to manipulate or validate incoming parameters before forwarding them to the superclass.