Classes - multiple inheritance
In the last lesson we made the Catalog
class for cataloging
movies. However, there are other things we can catalog too, such as
music. Since cataloging both movies and music should have some common
functionalities, something we can do is create classes for them which
inherit a common ancestor class. When we do this, it is called
multiple inheritance, it means a class can
inherit properties from more than one class. This is typically a parent/child
relationship. What this often means is the parent is a generalized class
and the children are specialized classes. To create these classes, it will
look very similar to previously, with some extra work upfront to inherit and
initialize the parent class. Lets start with creating a class specifically for
cataloging movies. The Catalog
class will be the same as the previous lesson.
By writing Movie(Catalog)
, the Movie
class
inherits the Catalog
class. And the line
Catalog.__init__(self, title, release_year)
does the actual application of the attributes and methods from the Catalog
class to the Movie
class.
Why is this useful? Multiple inheritance allows a child class to access
methods and properties from all its parent classes. This means we can
use and modify instance variables defined in any of the parent
classes by referring to them with self. To initialize these
variables, we use the __init__
method in the child class,
similar to how we would normally invoke a method. Additionally, creating
a child class under this system lets us add more specific parameters and
functions tailored to the child class's needs. This brings up an
important question: how do function calls work when they are defined in
both the parent and the child classes?
In the following code editor we initialize a movie object from the
Movie
class. Note that the code from the previous
code editor is present but hidden in the following code block so we
can focus on the new content. The way
calling functions works in multiple
inheritance is to work up the child/parent inheritance tree. So if a
function is found in the child class, it will use it. If it's not, the
interpreter will search its parent (or parents). If it is there, then it
will use that. Additionally, a child class can call a parent class in the
same way we called its __init__
function. We have a few
examples here. The update_duration
function is not found in
the parent class, but is in the child class. The
update_release_year
and __str__
are not found in
the child class, but are in the parent class, so those will be used.
The update_title
function is found in both. In this case, it
will call the one found in the child first. Since it's written to call the
parent function with a slightly different parameter edit, we can do that
as well.
If we have a class that inherits from multiple parents, then it will search
the order of inheritance based on which came first. For example if we made a class
as: A(B,C)
, then when an
instance of A is created, the interpreter will search A first, followed by
B, then C.
Practice Questions
Use the following code for the following questions.
class Character:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"{self.name} ({self.age})"
class Human(Character):
def __init__(self, name, age):
Character.__init__(self, name, age)
def __str__(self):
return f"Human: {self.name} ({self.age})"
class Elf(Character):
def __init__(self, name, age, affinity):
Character.__init__(self, name, age)
self.affinity = affinity
def __str__(self):
return f"Elf: {self.name} ({self.age})"
def get_affinity(self):
return self.affinity
class HalfElf(Human, Elf):
def __init__(self, name, age, affinity):
Human.__init__(self, name, age)
Q01.a. What will print when we run this code?
lizette = HalfElf("lizette", 19, "hydro")
print(lizette, lizette.get_affinity())
Q01.b. If we initialize both Human and Elf such as in the code below, what will print?
class HalfElf(Human, Elf):
def __init__(self, name, age, affinity):
Human.__init__(self, name, age)
Elf.__init__(self, name, age, affinity)
Q01.c. What will print if we change the order of inheritance?
class HalfElf(Elf, Human):
def __init__(self, name, age, affinity):
Human.__init__(self, name, age)
Elf.__init__(self, name, age, affinity)
score: 0%