
Overriding and super
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 e-mail 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, 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 is 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. For example:
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 correct some problems in this example. Our Contact
and Friend
classes have duplicate code to set up the name
and email
properties; this can make 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 call code on the parent 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, not just __init__
. This means 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 in the method. For example, we may need to manipulate the incoming parameters before forwarding them to the superclass.