12.16. OOP Inheritance Overload

12.16.1. Rationale

  • Child inherits all fields and methods from parent

  • Used to avoid code duplication

overload

When child has method or attribute with the same name as parent. In such case child attribute will be used (will overload parent).

12.16.2. Method Overload

>>> class Parent:
...     def say_hello(self):
...         print('hello')
>>>
>>>
>>> class Child(Parent):
...     def say_hello(self):
...         print('yo')
>>>
>>>
>>> obj = Child()
>>> obj.say_hello()
yo

12.16.3. super()

  • Calls a method from superclass

  • Order/location is important

  • Raymond Hettinger - Super considered super! - PyCon 2015 [#Hettinger2015]_

12.16.4. Super With Methods

>>> class Parent:
...     def say_hello(self):
...         print('hello')
>>>
>>>
>>> class Child(Parent):
...     def say_hello(self):
...         super().say_hello()
...         print('yo')
>>>
>>>
>>> obj = Child()
>>> obj.say_hello()
hello
yo

Order of super() is important:

>>> class Parent:
...     def say_hello(self):
...         print('hello')
>>>
>>>
>>> class Child(Parent):
...     def say_hello(self):
...         print('yo')
...         super().say_hello()
>>>
>>>
>>> obj = Child()
>>> obj.say_hello()
yo
hello

12.16.5. Attribute Overload

>>> class Parent:
...     def __init__(self):
...         self.firstname = 'Mark'
...         self.lastname = 'Watney'
>>>
>>>
>>> class Child(Parent):
...     def __init__(self):
...         self.job = 'astronaut'
>>>
>>>
>>> obj = Child()
>>> vars(obj)
{'job': 'astronaut'}

12.16.6. Super With Attributes

>>> class Parent:
...     def __init__(self):
...         self.firstname = 'Mark'
...         self.lastname = 'Watney'
>>>
>>>
>>> class Child(Parent):
...     def __init__(self):
...         super().__init__()
...         self.job = 'astronaut'
>>>
>>>
>>> obj = Child()
>>> vars(obj)
{'firstname': 'Mark', 'lastname': 'Watney', 'job': 'astronaut'}

12.16.7. Super Attributes Problem

Note, that the problem exists when Parent and a Child defines attribute with the same name. Than while calling super() it will overload field value.

>>> class Parent:
...     def __init__(self):
...         self.firstname = 'Mark'
...         self.lastname = 'Watney'
...         self.job = 'unemployed'
>>>
>>>
>>> class Child(Parent):
...     def __init__(self):
...         super().__init__()
...         self.job = 'astronaut'
>>>
>>>
>>> obj = Child()
>>> vars(obj)
{'firstname': 'Mark', 'lastname': 'Watney', 'job': 'astronaut'}
>>> class Parent:
...     def __init__(self):
...         self.firstname = 'Mark'
...         self.lastname = 'Watney'
...         self.job = 'unemployed'
>>>
>>>
>>> class Child(Parent):
...     def __init__(self):
...         self.job = 'astronaut'
...         super().__init__()
>>>
>>>
>>> obj = Child()
>>> vars(obj)
{'job': 'unemployed', 'firstname': 'Mark', 'lastname': 'Watney'}

12.16.8. Assignments

Code 12.25. Solution
"""
* Assignment: OOP Overload Super
* Required: yes
* Complexity: easy
* Lines of code: 6 lines
* Time: 5 min

English:
    1. Create class `Astronaut` which inherits from `Person`
    2. Class `Astronaut` takes two arguments `name` and `mission`
    3. Set attribute `mission` in `Astronaut` inicializer method
    4. Call initializer method of `Person` passing `name` as an argument
    5. Define method `show()` returning name and after coma - a mission name
    6. Run doctests - all must succeed

Polish:
    1. Stwórz klasę `Astronaut` dziedziczącą po `Person`
    2. Klasa `Astronaut` przyjmuje dwa argumenty `name` i `mission`
    3. Ustaw atrybut `mission` w metodzie inicjalizacyjnej w `Astronaut`
    4. Wywołaj metodę inicjalizacyjną z `Person` podając `name` jako argument
    5. Zdefiniuj metodę `show()` zwracającą imię i po przecinku - nazwę misji
    6. Uruchom doctesty - wszystkie muszą się powieść

Tests:
    >>> import sys; sys.tracebacklimit = 0

    >>> watney = Astronaut('Watney', 'Ares 3')
    >>> watney.show()
    'Watney, Ares 3'
    >>> lewis = Astronaut('Lewis', 'Ares 3')
    >>> lewis.show()
    'Lewis, Ares 3'
"""


class Person:
    def __init__(self, name):
        self.name = name