4.7. Inheritance Aggregation

4.7.1. Diagram

../../_images/inheritance-usecase-aggregation.png

4.7.2. Code

class TupleSerializer:
    def astuple(self, instance):
        data = [v for v in vars(instance).values()]
        return tuple(data)


class DictSerializer:
    def asdict(self, instance):
        data = {k: v for k, v in vars(instance).items()
                if not k.startswith('_')}
        return dict(data)


class Account:
    serializers: list = []

    def __init__(self, firstname, lastname):
        self.firstname = firstname
        self.lastname = lastname

    def astuple(self):
        for serializer in self.serializers:
            if hasattr(serializer, 'astuple'):
                return serializer.astuple(self)
        clsname = self.__class__.__name__
        error = f"'{clsname}' object has no attribute 'astuple'"
        raise AttributeError(error)

    def asdict(self):
        for serializer in self.serializers:
            if hasattr(serializer, 'asdict'):
                return serializer.asdict(self)
        clsname = self.__class__.__name__
        error = f"'{clsname}' object has no attribute 'asdict'"
        raise AttributeError(error)


class User(Account):
    serializers = []


class Staff(Account):
    serializers = [TupleSerializer()]


class Admin(Account):
    serializers = [TupleSerializer(), DictSerializer()]

4.7.3. Usage

>>> mark = User('Mark', 'Watney')
>>>
>>> mark.astuple()
Traceback (most recent call last):
AttributeError: 'User' object has no attribute 'astuple'
>>>
>>> mark.asdict()
Traceback (most recent call last):
AttributeError: 'User' object has no attribute 'asdict'
>>> rick = Staff('Rick', 'Martinez')
>>>
>>> rick.astuple()
('Rick', 'Martinez')
>>>
>>> rick.asdict()
Traceback (most recent call last):
AttributeError: 'Staff' object has no attribute 'asdict'
>>> melissa = Admin('Melissa', 'Lewis')
>>>
>>> melissa.astuple()
('Melissa', 'Lewis')
>>>
>>> melissa.asdict()
{'firstname': 'Melissa', 'lastname': 'Lewis'}

4.7.4. Use Case - 0x01

>>> class Permission:
...     pass
>>>
>>> class ProfileEdit(Permission):
...     def edit_profile(self): ...
>>>
>>> class ProfileDelete(Permission):
...     def delete_profile(self): ...
>>>
>>> class UserDelete(Permission):
...     def user_delete(self): ...
>>>
>>> class UserEdit(Permission):
...     def user_edit(self): ...
>>>
>>>
>>> class MyAccount:
...     permissions: list[Permission] = []
...
...     def edit_profile(self):
...         for permission in self.permissions:
...             if hasattr(permission, 'edit_profile'):
...                 return permission.edit_profile()
...         raise PermissionError('Cannot edit permission')
>>>
>>> mark = MyAccount()
>>> mark.permissions.append(ProfileEdit())
>>> mark.permissions.append(ProfileDelete())