Контекст
Насколько я понимаю, принципы инверсии зависимостей и разделения интерфейсов SOLID OOP предписывают нам писать нашу программу в соответствии с интерфейсом, а не внутренние детали. Итак, я пытаюсь разработать простой сборщик данных фондового рынка на Python, примерно со следующей объектной диаграммой, где main инкапсулирует бизнес-логику приложения, обработку пользовательского ввода и т. д. Вот как это понять< /p>- Розовый цвет представляет конкретную функцию или класс, зеленый — абстрактный класс.
- Полый наконечник стрелки представляет подкласс отношений/реализует. , а сплошная стрелка обозначает связь использование (в соответствии с соглашением Чистая архитектура Роберта Мартина)

Итак, основное Функция использует абстрактный интерфейс, который извлекает цену акции по символу. Абстрактный класс выглядит так:
Код: Выделить всё
#!/usr/bin/env python3
# encoding: utf-8
"""
Defines the abstract stock price reader
"""
from abc import ABC, abstractmethod
class StockPriceReader(ABC):
"""Defines the general tick reader interface."""
@abstractmethod
def get_price(self, symbol:str)->float:
"""
Gets the price of a stock represented by the symbol, e.g
when symbol='AAPL', it gets the Apple Inc stock price.
"""
raise NotImplementedError
Дилемма
Теперь, основываясь на приведенной выше простой диаграмме зависимостей классов, то же самое книга (Чистая архитектура), похоже, подразумевает это (здесь я подчеркиваю)Основной блок должен даже не знать что TickReaderConcrete существует.
По крайней мере, я так понимаю, о чем говорит книга, поскольку на главной странице нет стрелки в TickReaderConcrete, поправьте меня, если я ошибаюсь.
Но когда я пишу main.py, я не могу притворяться, что TickReaderConcrete > существует, другими словами, кажется основным не может не знать о существовании TickReaderConcrete, когда код выглядит так:
Код: Выделить всё
#!/usr/bin/env python3
# encoding: utf-8
"""
The main function to invoke the stockprice reader
"""
from tickreader import TickReaderConcrete
...
if __name__ == '__main__':
# This line gives rise to the alternative class diagram below
reader=TickReaderConcrete(...)
# After initialised, we can use the interface permitted by the abstract base class
reader.get_price(symbol='IBM')
Так как же сделать так, чтобы основной не знал о существовании конкретного читателя? Если main вообще не импортирует конкретный объект чтения, он не может даже создать экземпляр конкретного объекта чтения, а абстрактный модуль чтения все равно не может быть инициализирован.
Итак, как в принципе организовать код для правильной реализации объектной диаграммы выше?
Слегка перефразированный вопрос
Даже если абстрактный базовый класс предоставляет необходимые общедоступные методы, по крайней мере, инициализацию< /em> требует знания о существовании конкретного подкласса. Может ли конкретный подкласс спрятаться за абстрактным базовым классом? Посмотрите на альтернативную объектную диаграмму, которая реализована в приведенном выше фрагменте кода. Как избавиться от ломаной линии?

Подробнее здесь: https://stackoverflow.com/questions/781 ... concrete-c