Используется в python, в форме (обычно) абстрактных классов.
Цель варьируется, в Java они решают множественное наследование, в Python они действуют как контракт между 2 классами.
Класс A что-то делает, и часть этого что-то включает в себя класс B. Класс B может быть реализован несколькими способами, поэтому вместо создания 10 различных классов и НАДЕЖДЫ они будут использоваться должным образом, вы наследуете от абстрактного класса ( интерфейс), и вы должны убедиться, что они должны реализовать все методы, определенные как абстрактные. (ОБРАТИТЕ ВНИМАНИЕ, ЕСЛИ ОНИ НЕ РЕАЛИЗУЮТ ЛЮБОГО МЕТОДА, КОТОРЫЕ ОНА БУДЕТ РАСПРОСТРАНЯТЬСЯ ВО ВРЕМЯ СТРОИТЕЛЬСТВА, КОГДА ВЫ УСТАНАВЛИВАЕТЕ УПАКОВКУ, НЕ КОГДА ВЫ ЗАПУСКАЕТЕ ЭТО ОЧЕНЬ ВАЖНО В СРЕДНИХ / БОЛЬШИХ ПРОЕКТАХ).
Вы также знаете, что ЛЮБОЙ класс, который реализует эти методы, будет работать с классом, который его использует. Это звучит тривиально, но деловая сторона ЛЮБИТ это, потому что это означает, что вы можете передать часть своего кода на аутсорсинг, и он подключится и будет работать с остальным кодом.
Из того, что я понимаю, интерфейсы говорят классу, что он может делать, а не как это делать. Это означает, что в какой-то момент классу нужно рассказать, как делать методы.
Они на самом деле говорят ему, что он ДОЛЖЕН делать, о том, как они это делают, нам все равно.
Если это так, какой смысл в интерфейсах? Почему бы просто не определить метод в классе?
Дело не в этом, но да, абсолютно необходимо определение метода в классе, который наследуется от интерфейса.
Давайте приведем более конкретный пример.
Представьте, что у вас есть среда разработки Python, которая выполняет некоторые задачи. Задачи могут выполняться локально (на том же компьютере, на котором работает среда Python), они могут выполняться в распределенной системе, отправляя их в какой-то центральный планировщик, они могут выполняться в док-контейнере на веб-сервисах Amazon .... Вы поняли.
Все, что вам нужно, - это интерфейс (абстрактный класс в Python), который имеет метод run_task, в зависимости от того, какой из них вы используете.
например:
class Runner:
__metaclass__ = abc.ABCMeta
@abstractmethod
def run_task(self, task_command):
return
class LocalRunner(Runner):
def run_task(self, task_command):
subprocess.call(task_command)
class SlurmRunner(Runner):
def run_task(self, task_command):
subprocess.call('sbatch ' + task_command)
Теперь важный момент, как вы, возможно, спросите. Зачем мне все эти ^ $ ^ $%?
осложнения? (вероятно, вы этого не сделаете, если проект yopur достаточно мал, но есть точка останова в зависимости от размера, когда вам почти НЕОБХОДИМО начать использовать эти вещи).
Класс, который использует ТОЛЬКО бегуна, должен понимать интерфейс, например у вас есть класс Task, этот класс может делегировать выполнение задачи TaskRunner, в зависимости от того, какая из них вам не нужна, они в некотором смысле полиморфны.
class Task:
def __init__(self, task_runner):
self.task_runner = task_runner
self.task_command = 'ls'
def run_this_task(self):
self.task_runner.run_task(self.task_command)
И, если вы какой-то программист, ваш босс может сказать вам, мне нужен новый класс, который выполняет команды в AWS, вы присваиваете ему команду, и она реализует метод task_runner, тогда вам НЕ нужно знать НИЧЕГО об остальных код, вы можете реализовать этот бит как полностью изолированную часть (это часть аутсорсинга, теперь у вас может быть 100 человек, проектирующих 100 различных программ [т.е. им не нужно ничего знать о коде, только интерфейсы) .