@Bayfong

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

Я только начинаю изучать программирование.
Итак, насколько я понял, интерфейс-это набор методов, которые реализуются только у потомков(классов).
В свою очередь, абстрактный класс может создавать абстрактные методы, который буквально равны методам интерфейсов, так еще и может создавать обычные методы с готовой реализацией.
Так зачем вообще нужны интерфейсы, если все можно делать с помощью абстрактных классов?
  • Вопрос задан
  • 157 просмотров
Решения вопроса 1
Adamos
@Adamos
Наоборот. Абстрактный класс имеет смысл использовать только тогда, когда не можешь обойтись интерфейсом.
Однако "только начав изучать программирование", не стоит тратить время впустую на такие вопросы.
Практика и опыт дадут на них ответ куда лучше, чем десяток отвечающих на Тостере.
Ответ написан
Пригласить эксперта
Ответы на вопрос 4
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, где классы содержат только функции (в ФП больше ничего и нет), но их решили не называть интерфейсами.
Ответ написан
Комментировать
Vapaamies
@Vapaamies
Разработчик будущей ОС для ПК размером 250 МБ
Это казуистика.
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы
ВТЮРИН Севастополь
от 30 000 до 70 000 ₽
Big Smile Coffee Санкт-Петербург
от 150 000 до 200 000 ₽
Ведисофт Екатеринбург
от 25 000 ₽
03 мар. 2024, в 01:13
20000 руб./за проект
02 мар. 2024, в 23:44
1000 руб./в час