C ++ объяснение.
Думайте об интерфейсе как о ваших открытых методах классов.
Затем вы можете создать шаблон, который «зависит» от этих открытых методов, чтобы выполнять свою собственную функцию (она делает вызовы функций, определенные в общедоступном интерфейсе классов). Допустим, этот шаблон является контейнером, как класс Vector, а интерфейс, от которого он зависит, является алгоритмом поиска.
Любой класс алгоритма, который определяет функции / интерфейс, к которым Vector обращается, будет удовлетворять «контракту» (как кто-то объяснил в первоначальном ответе). Алгоритмы даже не должны быть одного и того же базового класса; единственное требование - чтобы в вашем алгоритме были определены функции / методы, от которых зависит Вектор (интерфейс).
Смысл всего этого в том, что вы можете указать любой другой алгоритм / класс поиска, если он предоставляет интерфейс, от которого зависит Vector (пузырьковый поиск, последовательный поиск, быстрый поиск).
Возможно, вы захотите разработать другие контейнеры (списки, очереди), которые будут использовать тот же алгоритм поиска, что и Vector, если они будут выполнять интерфейс / контракт, от которого зависят ваши алгоритмы поиска.
Это экономит время (принцип ООП «повторное использование кода»), поскольку вы можете написать алгоритм один раз, а не снова и снова и снова, специфично для каждого нового объекта, который вы создаете, без чрезмерного усложнения проблемы с заросшим деревом наследования.
Что касается «упущения» в отношении того, как все происходит; большой (по крайней мере, в C ++), поскольку именно так работает большая часть стандартной библиотеки ШАБЛОНОВ.
Конечно, при использовании наследуемых и абстрактных классов меняется методология программирования интерфейса; но принцип тот же, ваши открытые функции / методы - это интерфейс ваших классов.
Это огромная тема и один из основополагающих принципов шаблонов проектирования.