Multiple Inheritance Example

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.

../../_images/multiple_inheritance_example_bw.png

Note

You can click the above image to expand it!

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.

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.

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
example.py#
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 AwesomeShip class that adds the torpedo rounds from the attack ship, infinite cargo capacity and defensive shields.

../../_images/awesome_ship.png

The AwesomeShip class should inherit from the following independent classes in order:

  • Spaceship as provided

  • AttackShip as provided

  • ShieldedShip

  • InfiniteCargoShip

so that all the functionality is available and working aboard the ship

ShieldedShip Specifications

  • Attributes

    • shield_level

  • __init__ method with

    • Parameters

      • self

    • Actions

      • Set the shield_level to 100

  • damage method with

    • Parameters:

      • self

      • amount

    • Actions:

      • Reduces the shield level by the given amount down to 0.

    • Returns:

      • None (no return statement required)

  • recharge method with

    • Parameters:

      • self

    • Actions:

      • Resets the shield level to 100

InfiniteCargoShip Specifications

  • Attributes:

    • cargo_volume as described above

  • __init__ method with

    • Parameters:

      • self

      • name

      • fuel_capacity

    • Actions:

      • Call the Spaceship constructor to set common attributes with the same name

      • Set the cargo_volume attribute to 0

  • load_cargo method with

    • Parameters

      • self

      • volume

    • Actions

      • Increase the cargo_volume by the given volume

  • unload_cargo method with

    • Parameters

      • self

      • volume

    • Actions

      • Reduce the cargo_volume by the given volume down to 0.

AwesomeShip Specifications

  • Inherit from

    • Spaceship as provided

    • AttackShip as provided

    • ShieldedShip

    • InfiniteCargoShip

  • __init__ method with

    • Parameters:

      • self

      • name

      • fuel_capacity

      • rounds

    • Actions:

      • 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