2.8. Multiple Inheritance Example#
Let’s look at a complete example of multiple inheritance using the bank account context.
In this example we create a “Premium Savings Account” class
PremiumSavingsAccount, which combines savings account functionality with a
rewards point system by inheriting from two classes, each responsible for
different functions.
Note
You can click the above image to expand it!
2.8.1. Base and Savings Accounts#
These classes should look familiar from earlier examples. The
SavingsAccount class inherits from BaseAccount and adds a basic
interest calculation method.
2.8.2. Rewards Account#
The RewardsAccount class is a “mixin” and is independent from any other
class. It overrides the deposit method to add rewards points each time a
deposit is made.
2.8.3. Premium Savings Account#
The PremiumSavingsAccount only needs to inherit from the SavingsAccount
and RewardsAccount classes as they already implement the required
functionality. Because of the multiple inheritance we have to manually call the
constructors of parent classes.
The order of the inheritance is critical for the deposit functionality to work because of the MRO.
class PremiumSavingsAccount(RewardsAccount, SavingsAccount):
If we swapped the order, then SavingsAccount.deposit would be called
instead of RewardsAccount.deposit when using PremiumSavingsAccount.
It’s important to note that we are treating the constructors as normal
functions and need to manually pass self:
SavingsAccount.__init__(self, bsb_number, account_number, balance, holder_name, interest_rate)
RewardsAccount.__init__(self) # Initialize the rewards system
class BaseAccount:
def __init__(self, bsb_number, account_number, balance, holder_name):
self.bsb_number = bsb_number
self.account_number = account_number
self.balance = balance
self.holder_name = holder_name
def deposit(self, amount):
self.balance += amount
def withdraw(self, amount):
self.balance -= amount
class SavingsAccount(BaseAccount):
def __init__(self, bsb_number, account_number, balance, holder_name, interest_rate):
super().__init__(bsb_number, account_number, balance, holder_name)
self.interest_rate = interest_rate
def get_earned_interest(self):
return self.balance * self.interest_rate
class RewardsAccount:
def __init__(self):
self.reward_points = 0
def add_rewards(self, amount):
points_earned = amount * 0.1 # 1 point per $10 deposited
self.reward_points += points_earned
def deposit(self, amount):
super().deposit(amount) # Call the deposit method from BaseAccount
self.add_rewards(amount) # Also apply rewards system
class PremiumSavingsAccount(RewardsAccount, SavingsAccount):
def __init__(self, bsb_number, account_number, balance, holder_name, interest_rate):
SavingsAccount.__init__(
self, bsb_number, account_number, balance, holder_name, interest_rate
)
RewardsAccount.__init__(self) # Initialize the rewards system
# Example Usage
premium_acc = PremiumSavingsAccount("689716", "62228626", 19.39, "Bruce Wayne", 0.0235)
premium_acc.deposit(500) # Adds money and rewards points
print("Interest Earned:", premium_acc.get_earned_interest()) # Check interest
print("Total Reward Points:", premium_acc.reward_points) # Check rewards points
Code Challenge: Awesome Ship
Note
For this exercise you should have completed Super > “Attack Ship”, Hierarchical Inheritance > “Infinite Cargo Ship” and Multilevel Inheritance > “Shield Up”
You think to yourself “Why have we been making separate ships with different abilities?” What about a ship with everything?!
Make an
AwesomeShipclass that adds the torpedo rounds from the attack ship, infinite cargo capacity and defensive shields.![]()
The
AwesomeShipclass should inherit from the following independent classes in order:
Spaceshipas provided
AttackShipas provided
ShieldedShip
InfiniteCargoShipso that all the functionality is available and working aboard the ship
ShieldedShip Specifications
Attributes
shield_level
__init__method with
Parameters
selfActions
Set the
shield_levelto 100
damagemethod with
Parameters:
self
amountActions:
Reduces the shield level by the given amount down to
0.Returns:
None(no return statement required)
rechargemethod with
Parameters:
selfActions:
Resets the shield level to
100InfiniteCargoShip Specifications
Attributes:
cargo_volumeas described above
__init__method with
Parameters:
self
name
fuel_capacityActions:
Call the Spaceship constructor to set common attributes with the same name
Set the
cargo_volumeattribute to0
load_cargomethod with
Parameters
self
volumeActions
Increase the
cargo_volumeby the given volume
unload_cargomethod with
Parameters
self
volumeActions
Reduce the
cargo_volumeby the given volume down to0.AwesomeShip Specifications
Inherit from
Spaceshipas provided
AttackShipas provided
ShieldedShip
InfiniteCargoShip
__init__method with
Parameters:
self
name
fuel_capacity
roundsActions:
Call all parent class constructors
Here is some code for you to start with:
class Spaceship: def __init__(self, name, fuel_capacity): self.name = name self.fuel_weight = 0 self.fuel_capacity = fuel_capacity def refuel(self, weight): if self.fuel_weight + weight > self.fuel_capacity: self.fuel_weight = self.fuel_capacity else: self.fuel_weight += weight def fire_laser(self): if self.fuel_weight >= 10: self.fuel_weight -= 10 class AttackShip(): def __init__(self, rounds): self.rounds = rounds def fire_round(self): if self.rounds > 1: self.rounds -= 1 # ADD YOUR CLASSES HERE class AwesomeShip(Spaceship, AttackShip): def __init__(self, name, fuel_capacity, rounds): Spaceship.__init__(self, name, fuel_capacity) AttackShip.__init__(self)Solution
Solution is locked
