donghyun208
donghyun208

Reputation: 4857

Python design patterns: Nested Abstract Classes

In the following example code, I want every car object to be composed of brake_system and engine_system objects, which are stored as attributes on the car.

To implement this, I've defined Car, BreakSystem and EngineSystem as abstract classes. Every subclass of Car is required to define its respective BreakSystem and EngineSystem subclasses as class attributes.

Are there any potential problems with this approach? Or are there other design patterns better suited to handle nested abstractions?

from abc import ABC, abstractmethod

class Car(ABC):
    """
    every car object should have an Engine object and a BrakeSystem object
    """

    def __init__(self):
        self.engine_system = self._engine_type()
        self.brake_system = self._brake_type()

    @property
    @abstractmethod
    def _engine_type(self):
        raise NotImplementedError()

    @property
    @abstractmethod
    def _brake_type(self):
        raise NotImplementedError()

class EngineSystem(ABC):
    pass

class BrakeSystem(ABC):
    pass


class FooBrakeSystem(BrakeSystem):
    pass

class FooEngineSystem(EngineSystem):
    pass

class FooCar(Car):
    _engine_type = FooEngineSystem
    _brake_type = FooBrakeSystem

if __name__ == '__main__':
    obj = FooCar()

Upvotes: 7

Views: 4531

Answers (2)

Dmytro Serdiuk
Dmytro Serdiuk

Reputation: 959

I want every car object to be composed of brake_system and engine_system objects

You have abstract classes for the systems

class EngineSystem(ABC):
    pass

class BrakeSystem(ABC):
    pass

A car has to consists of two systems:

class Car:

    def __init__(self, engine: EngineSystem, brake: BrakeSystem):
        self._engine_system = engine
        self._brake_system = brake

    @property
    def engine_type(self) -> EngineSystem:
        return self._engine_system

    @property
    def brake_type(self) -> BrakeSystem:
        return self._engine_system

And now, if you need to create a specific car

tesla = Car(ElectroEngine(), Disks())

# or even 
class Tesla(Car):
    def __init__(self):
        super().__init__(ElectroEngine(), Disks())

tesla = Tesla()

This approach allows you to create a car as a composition of its systems.

Upvotes: 9

Atul Dwivedi
Atul Dwivedi

Reputation: 1462

I'm beginner in python.

Answering your question on the basis of OO concepts, It is perfectly fine to have nested abstraction to enforce the implementer to must define what outer class encapsulates. And I do not see any potential problem in this structure.

In your example Car has BreakSystem and EngineSystem makes perfect sense when one has to simulate real word entities as software and at the same time all are very generic so having them as abstract is acceptable and letting the implementer to define the details in concrete classes.

This can also be simulated if you have composition, Example one can have Building and Room as abstract types (where Building is composed of Rooms), and using Flat/House this can be realized where House/Flat has Rooms like DiningRoom and/or DrawingRoom etc.

Upvotes: 0

Related Questions