22.4. Invoking the Parent Class’s Method

Sometimes the parent class has a useful method, but you just need to execute a little extra code when running the subclass’s method. You can override the parent class’s method in the subclass’s method with the same name, but also invoke the parent class’s method. Here’s how.

Say you wanted the Dog subclass of Pet to say “Arf! Thanks!” when the feed method is called, as well as executing the code in the original method.

Here’s the original Pet class again.

And here’s a subclass that overrides feed() by invoking the the parent class’s feed() method; it then also executes an extra line of code. Note the somewhat inelegant way of invoking the parent class’ method. We explicitly refer to Pet.feed to get the method/function object. We invoke it with parentheses. However, since we are not invoking the method the normal way, with <obj>.methodname, we have to explicitly pass an instance as the first parameter. In this case, the variable self in Dog.feed() will be bound to an instance of Dog, and so we can just pass self: Pet.feed(self).

Note

There’s a better way to invoke a superclass’s method. Unfortunately, the implementation of python in our ActiveCode windows doesn’t support it, so we aren’t using it here. In that alternative method, we would call super().feed(). This is nice because it’s easier to read, and also because it puts the specification of the class that Dog inherits from in just one place, class Dog(Pet). Elsewhere, you just refer to super() and python takes care of looking up that the parent (super) class of Dog is Pet.

This technique is very often used with the __init__ method for a subclass. Suppose that some extra instance variables are defined for the subclass. When you invoke the constructor, you pass all the regular parameters for the parent class, plus the extra ones for the subclass. The subclass’ __init__ method then stores the extra parameters in instance variables and calls the parent class’ __init__ method to store the common parameters in instance variables and do any other initialization that it normally does.

Let’s say we want to create a subclass of Pet, called Bird, and we want it to take an extra parameter, chirp_number, with a default value of 2, and have an extra instance variable, self.chirp_number. Then, we’ll use this in the hi method to make more than one sound.

Check your understanding

    intro-9-1: What will print when print(b1.sounds) is run?
  • 5
  • This would print if the code was print(b1.chirp_number).
  • ["Mrrp"]
  • We set b1 to be Bird('tweety', 5) above. Bird is a subclass of Pet, which has ["Mrrp"] for sounds, but Bird has a different value for that class variable. The interpreter looks in the subclass first.
  • ["chirp"]
  • The interpeter finds the value in the class variable for the class Bird.
  • Error
  • We ran set b1 to be Bird('tweety', 5) above. Bird has a value set for the attribute sounds.
    intro-9-2: For the Dog class defined in the earlier activecode window, what would happen when d1.feed() is run if the Pet.feed(self) line was deleted?
  • Error when invoked
  • Since we are no longer calling the parent method in the subclass method definition, the actions defined in the parent method feed will not happen, and only Arf! Thanks! will be printed.
  • The string would not print out but d1 would have its hunger reduced.
  • Remember that the Python interpreter checks for the existence of feed in the Dog class and looks for feed in Pet only if it isn't found in Dog.
  • The string would print but d1 would not have its hunger reduced.
  • Since we are no longer calling the parent Pet class's method in the Dog subclass's method definition, the class definition will override the parent method.
  • Nothing would be different. It is the same as the current code.
  • Remember that the Python interpreter checks for the existence of feed in the Dog class and looks for feed in Pet only if it isn't found in Dog.
Next Section - 22.5. Tamagotchi Revisited