@Bayfong

Зачем нужен интерфейс, если есть абстрактный класс?

Я только начинаю изучать программирование.
Итак, насколько я понял, интерфейс-это набор методов, которые реализуются только у потомков(классов).
В свою очередь, абстрактный класс может создавать абстрактные методы, который буквально равны методам интерфейсов, так еще и может создавать обычные методы с готовой реализацией.
Так зачем вообще нужны интерфейсы, если все можно делать с помощью абстрактных классов?
  • Вопрос задан
  • 183 просмотра
Решения вопроса 1
Adamos
@Adamos
Наоборот. Абстрактный класс имеет смысл использовать только тогда, когда не можешь обойтись интерфейсом.
Однако "только начав изучать программирование", не стоит тратить время впустую на такие вопросы.
Практика и опыт дадут на них ответ куда лучше, чем десяток отвечающих на Тостере.
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
delphinpro
@delphinpro
frontend developer
Класс может реализовать множество интерфейсов, но унаследовать только один абстрактный класс. Ну по крайней мере в определенных языках, про все не скажу.
Ответ написан
@Mercury13
Программист на «си с крестами» и не только
Разрешите добавить. Интерфейс, грубо говоря,— это абстрактный класс без данных и недописанных функций (каждая или полностью жизнеспособна в какой-то ситуёвине, или нулевая = полностью абстрактная, не путать с пустой). И причины этому две.

1. Организационная. Говорит программистам: не ставьте тут абстрактный класс, если можно интерфейс. Так кузявее: не стоит подключать большую артиллерию, когда можно обойтись малой кровью.

2. Техническая. Прикрывает один такой серьёзный жупел, как ромбическое наследование данных. Ромбическое наследование данных бывает двух видов.
Пусть у нас такое:
class Grandfather { public: int field; };
class LeftFather : Grandfather {};
class RightFather : Grandfather {};
class Son : LeftFather, RightFather {};

а) С дублированием, когда у сына два поля field, унаследованное через левого отца и через правого. Достаточно сделать функцию…
void foo(LeftFather& x) { x.field = 42; }
Как сохранить синхронизацию для левой и правой ветки наследования?
б) С общим дедом, когда у сына одно такое поле (через виртуальное наследование Си++). Тут левая и правая ветки могут быть просто не готовы к тому, что поле будет меняться без её ведома.

Ромбическое наследование функций не так вредно: ведь любая функция, извините, работает с данными. А значит, она или имеет дело с внешними данными (а значит, в обеих ветках сделает одно и то же), или нулевая, или просто комбинация таких же нулевых (InputStream.remainder() { return size() - pos(); }).

Почему я говорю «в какой-то ситуёвине». Возьмём тот же remainder. Существуют потоки — скажем, закэшированный ввод с внешнего устройства — которые не имеют размера и позиции, но способны иметь остаток. Для каких-то потоков можно написать остаток более эффективный. Но это казуистика.
Ответ написан
Комментировать
@AlexSku
не буду отвечать из-за модератора
Возможно, чисто исторически интерфейсы появились раньше.
В C/C++ как только появились классы, структуры никто отменять не стал.
Есть пример в Haskell, где классы содержат только функции (в ФП больше ничего и нет), но их решили не называть интерфейсами.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы