Inheritance (Part 2)¶
Add New Properties to Child Class¶
An EVCar
object needs two properties that are not defined in the Car
class: battery_size
and charge_level
.
To include these, we must define an __init__
method inside the EVCar
class. The idea is to inherit all of the property names from the Car
class
and just add the two new ones.
The general syntax for this is:
1 2 3 4 5 6 7 | class ChildClassName(ParentClassName):
def __init__(self, parent_properties, new_property):
# First, set the properties found in ParentClassName.
ParentClassName.__init__(self, parent_properties)
# Next, assign a value to the new property.
self.new_property = new_property
|
When we call the child class, the __init__
method runs in two parts. First,
it calls the parent class and completes that initialization. Next, control
returns to the __init__
method in the child class, and values are assigned
to any additional properties.
Line 3 defines the initializer method for the child class. Note that the parameters include
self
and variables for both the parent and child properties.Line 5 calls the
__init__
method from the parent class. This assigns values to all properties inherited from that class.Line 7 creates a new property name and assigns it a value.
Example
Let’s see how this works for our EVCar
class:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | class Car:
def __init__(self, make, model, year, color):
self.make = make
self.model = model
self.year = year
self.color = color
def honk_horn(self):
return "Beep!"
class EVCar(Car):
def __init__(self, make, model, year, color, battery_size):
# Call the Car __init__ method and assign the inherited properties.
Car.__init__(self, make, model, year, color)
# Initialize properties specific to the EVCar class.
self.battery_size = battery_size
self.charge_level = 100 # Begin with 100% charge.
def recharge(self):
# Code for recharging the battery.
return "Fully charged!"
def main():
my_car = Car('Saturn', 'SW-1', 1999, 'green')
dream_car = EVCar('Tesla', 'Model S', 2020, 'blue', '100 kWh')
print("my_car:", vars(my_car))
print("dream_car:", vars(dream_car))
if __name__ == '__main__':
main()
|
Console Output
my_car: {'make': 'Saturn', 'model': 'SW-1', 'year': 1999, 'color': 'green'}
dream_car: {'make': 'Tesla', 'model': 'Model S', 'year': 2020, 'color': 'blue', 'battery_size': '100 kWh', 'charge_level': 100}
Lines 27 and 28 print out the property names and values for the Car
and
EVCar
objects. Note that dream_car
includes two properties that are
missing from my_car
.
Change Existing Methods¶
On the previous page, we saw that EVCar
inherits the honk_horn()
method
from the Car
parent class. Any EVCar
object can call this method
without a problem. We also saw how to add a new method to a child class, like
the recharge()
and refuel()
methods for EVCar
and GasCar
,
respectively.
What if we want the parent and child class to share a method name, but we want the two functions to do different things?
Python and other programming languages allow us to override a method inherited from the parent class. The child class includes a method with the same name. However, instead of using the code from the parent class, the method contains a different set of instructions. These execute instead of the parent code.
Let’s see how this works with the honk_horn()
method.
Example
We can call the honk_horn()
method on a GasCar
object, but the sound
produced depends on the make
of the car.
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | class GasCar(Car):
def refuel(self):
# Code for refilling the gas tank.
return "Tank full."
def honk_horn(self):
if self.make == "BMW":
return "HONK!!!"
elif self.make == "Toyota":
return "Beep, beep."
elif self.make == "Plymouth":
return "ah-OOOO-gah"
else:
return Car.honk_horn(self)
def main():
hybrid = GasCar('Toyota', 'Prius', 2018, 'gray')
classic = GasCar('Plymouth', 'De Luxe', 1947, 'blue')
guzzler = GasCar('Ford','F-150', 2019, 'red')
print(hybrid.honk_horn())
print(classic.honk_horn())
print(guzzler.honk_horn())
if __name__ == '__main__':
main()
|
Console Output
Beep, beep.
ah-OOOO-gah
Beep!
In this case, code in the the GasCar
class (lines 16 - 24) overrides the
honk_horn()
method inherited from Car
. When we call the method on
hybrid
, classic
, and guzzler
, the code in the child class executes.
This gives our three objects the chance to return something different than a
Car
object.
Notice that if make
isn’t 'BMW'
, 'Toyota'
, or Plymouth
, then
the else
block executes:
23 24 | else:
return Car.honk_horn(self)
|
Line 24 essentially says: Return the same thing as a Car object. Thus, the
GasCar
honk_horn()
method includes the Car
behavior as a backup.
Try It!¶
In the editor below:
Define a
honk_horn()
method in theEVCar
class. For now, just have it return a string value that is different from'Beep!'
.In
main()
, confirm thatmy_car
anddream_car
behave differently when you use the objects to call thehonk_horn()
method.Expand the code in the child
honk_horn()
method to be more interesting than a singlereturn
statement. Be sure to include logic that calls the parent method if certain conditions are met.
Wrap-Up¶
Inheritance allows us to define new data types by extending the code from
previously defined types, like the relationship between Car
and EVCar
.
A child class like EVCar
inherits all the properties and methods of its
parent class. It can then define its own new properties and methods.
A child class can override methods inherited from the parent class but still access the original behavior.