from typing import Protocol

'''
Абстрактные базовые классы

- Абстракнтые классы нельзя использовать по отдельности, и их можно использовать
только путем реализации дочернего класса. Поэтому ABC по своей сути принадлежат
к своим подклассам как часть строгой иерархии классов.

- Хорошо подходят для проверки в реальном времени при создании экземпляра 
дочернего класса. ABC выдаст ошибку при инициализации, если дочерний элемент
не реализует все его абстрактные методы.

Протоколы

- Не используют иерархию.

- Используются в определенном месте и сообщают нижестоящему коду, какой
должна быть структура входного объекта. Протоколы принадлежат тому месту,
где они используются.

- Подходит для определения интерфейсов, особенно для сторонних библиотек, 
когда мы не хотим тесно связывать наш код с конкретной сторонней библиотекой.

Где спользовать

- Используйте ABC, если хотите повторно использовать код.

- Используйте ABC, если вам требуется строгая иерархия классов в вашем 
приложении.

- Используйте ABC, если вам понадобится несколько реализаций класса с 
несолькокими методами.

- Используйте протоколы для аннотаций строгого типа.

- Используйте протоколы для абстрактных интерфейсов для сторонних библиотек.

'''





class Animal(Protocol):
    def walk(self) -> None:
        ...

    def speak(self) -> None:
        ...


class Dog:
    def walk(self) -> None:
        print('This is dog walking')

    def speak(self) -> None:
        print('Woof!')

def make_animal_speak(animal: Animal) -> None:
    animal.speak()


def test_1():
    dog = Dog()
    make_animal_speak(dog)


def main():
    test_1()

if __name__ == '__main__':
    main()