FAQ: Learn Python: Inheritance and Polymorphism - Interfaces

This community-built FAQ covers the “Interfaces” exercise from the lesson “Learn Python: Inheritance and Polymorphism”.

Paths and Courses
This exercise can be found in the following Codecademy content:

Computer Science

FAQs on the exercise Interfaces

Join the Discussion. Help a fellow learner on their journey.

Ask or answer a question about this exercise by clicking reply (reply) below!

Agree with a comment or answer? Like (like) to up-vote the contribution!

Need broader help or resources? Head here.

Looking for motivation to keep learning? Join our wider discussions.

Learn more about how to use this guide.

Found a bug? Report it!

Have a question about your account or billing? Reach out to our customer support team!

None of the above? Find out where to ask other questions here!

2 posts were split to a new topic: Why do I need inheritance?

3 posts were split to a new topic: How can I create a polymorphism of classes?

The directions in this exercise seems to be missing steps to implement an Interface like the given example.

Please consider adding steps to this exercise that would reflect the narrative in the example.

One way to extend the exercise to match the construction of the example would be to extend the instructions to result in something like the following code.

class InsurancePolicy:
  def __init__(self, price_of_item):
    self.price_of_insured_item = price_of_item
  def __repr__(self):
    return "Insurance Policy"
  def get_rate(self):
    print(self.rate * self.price_of_insured_item)
class VehicleInsurance(InsurancePolicy):
  rate = .001
  def __repr__(self):
    return "Vehicle Insurance"
class HomeInsurance(InsurancePolicy):
  rate = .00005
  def __repr__(self):
    return "Home Insurance" 

pol1 = VehicleInsurance(100)
pol2 = HomeInsurance(200)

for i in [pol1, pol2]:
  print(i, "Rate: ")

Which should output:

Vehicle Insurance Rate: 
Home Insurance Rate: 
class InsurancePolicy:
  def __init__(self, price_of_item):
    self.price_of_insured_item = price_of_item
class VehicleInsurance(InsurancePolicy):
  def get_rate(self):
    return price_of_item * .001

class HomeInsurance(InsurancePolicy):
  def get_rate(self):
    return price_of_item * .00005

Can we use price_of_item instead of self.price_of_insured_item

the simple way to figure this out, would be to try. Have you tried? You can make an instance VehicleInsurance or HomeInsurance and call the method, see what happens?

In this code:

class Chess:
def init(self):
self.board = setup_board()
self.pieces = add_chess_pieces()

…how are we able to call methods in the constructor (i.e. before object is created)?

the class with all its methods exists before you create an instance/object.

Why do the instructions to this exercise put a period before ‘get rate’?

Give VehicleInsurance a .get_rate() method that takes self as a parameter.

Is this how you explain it is a method? Have i missed something about this?

methods are part of a class (like in this exercise), while a function is just stand-alone.

the dot make sense when you would call the method, but the method definition should just be def get_rate(self):

I am still unsure why do we need super() when making a class a subclass of another. Doesn’t a subclass automatically inherit all the methods and attributes of the parent class?

Thank you!

the child class does indeed inherit from parent class, but then the child class can overwrite a parent method. If you then also want to call parent method, you will need super()

1 Like

Can anyone help me understand repr better. I’m trying to use it to print the object data and not the location but im still not fully undertanding. heres my code.

class InsurancePolicy:
def init(self, price_of_item):
self.price_of_insured_item = price_of_item
def repr(self):
return “Your rate is {rate}.”.format(rate=self.get_rate)

class VehicleInsurance(InsurancePolicy):
def get_rate(self):
return .001 * self.price_of_insured_item

class HomeInsurance(InsurancePolicy):
def get_rate(self):
return .00005 * self.price_of_insured_item

home_insurance = HomeInsurance(78)

1 Like

never mind, I’m stupid and just realized i wasn’t calling the get_rate method lol.

For the Chess/Checkers example:

To follow this example out a bit, would a setup_board() method be set the same kind of way?

As the two games set up their boards differently, defining setup_board() to accept a class would yield a different piece-layout configuration.

Is there any benefit to that?
Is what I’m saying here even relevant to the Interface lesson?

Let me cut to the chase: something about setup_board() called by two different classes with no argument is making my brain itch. Please help me sort this out. Thanks!

EDIT: Unless the board literally only means a board, and pieces are set up according to their own methods for the pieces. Honestly gang, disregard. Took me a while, but I got there.

So you don’t have a question anymore?

one more piece of general advice: having functions that have a single responsibility makes your code very readable.

my question would be, why we didn’t need super() method to inherit price_of_item attribute to pass the exercise.

if i include: def __init__(self, price_of_item): super().__init__(price_of_item) in the VehicleInsurance(InsurancePolicy), then it works fine as well, but i don’t quite get why it works without.

By default child classes will inherit all property and methods of parent class. We only need __super__ when we overwrite a parent method (in child class) and need to call the parent method

1 Like

thanks for that. i guess previous lesson left me a bit confused, i thought that in the code:

class Sink:
  def __init__(self, basin, nozzle):
    self.basin = basin
    self.nozzle = nozzle
class KitchenSink(Sink):
  def __init__(self, basin, nozzle, trash_compactor=None):
    super().__init__(basin, nozzle)
    if trash_compactor:
      self.trash_compactor = trash_compactor

we needed super() method so the KitchenSink could inherit basin and nozzle from the sink.
so if i understand you right, if it wasn’t for the trash compactor and the only difference between the two sinks was , say, an extra method def check_for_food_waste(self), but no extra attributes in dunder init, then we wouldn’t need super() at all?

what is dunder?

If the __init__ method of KitchenSink class didn’t have an extra parameter, we wouldn’t need to overwrite the init method.

Once we start overwriting parent methods in child class, we can choice/decide whether or not we also need to call the parent method (using super())

we could also have done:

class KitchenSink(Sink):
  def __init__(self, basin, nozzle, trash_compactor=None):
    self.basin = basin
    self.nozzle = nozzle
    if trash_compactor:
      self.trash_compactor = trash_compactor

Although calling the parent constructor/init method is generally preferable, there might be cases/scenarios where you do not want to

you can also decide not to set the instance properties (self.basin and self.nozzle`) within the child class (KitchenSink). Would be an anti-pattern, but its possible

1 Like