Согласно Хербу Саттеру, следует предпочитать абстрактные интерфейсы (все чисто виртуальные функции) абстрактным классам в C ++, чтобы максимально отделить реализацию. Хотя я лично считаю, что это правило очень полезно, я недавно присоединился к команде со многими программистами на Java, и в коде Java это руководство, по-видимому, не существует. Функции и их реализации очень часто находятся в абстрактных классах. Так что я неправильно понял Херба Саттера даже для C ++ или есть общая разница в использовании абстрактных функций в C ++ по сравнению с Java. Являются ли абстрактные классы с кодом реализации более понятным в Java, чем в C ++, и если да, то почему?
java
c++
interfaces
abstract-class
Мартин
источник
источник
Ответы:
ООП имеет состав и замену.
C ++ имеет множественное наследование, специализацию шаблонов, встраивание и семантику значения / перемещения / указателя.
Java имеет единственное наследование и интерфейсы, семантику встраивания и ссылки.
Обычный способ, которым школа ООП использует эти языки, - это использование наследования для замены объекта и встраивания для композиции. Но вам также нужен общий предок и способ приведения во время выполнения (в C ++ называется
dynamic_cast
, в Java просто запрашивает интерфейс у другого).Ява делает все это своими собственными
java.lang.Object
корнями. C ++ не имеет предопределенного общего корня, поэтому вы должны по крайней мере определить его, чтобы прийти к одной и той же «картинке» (но это ограничивает некоторые возможности C ++ ...).После этого возможность иметь полиморфизм во время компиляции (например, CRTP) и семантическое значение может предложить и другие альтернативы тому, как концепция «объекта ООП» может быть перенесена в программу C ++.
Вы даже можете представить себе ересь, использующую вложение и неявное преобразование для управления заменой и частным наследованием для управления композицией, фактически инвертируя традиционную школьную парадигму. (Конечно, этот путь на 20 лет моложе другого, поэтому не ожидайте широкой поддержки сообщества в этом)
Или вы можете представить себе виртуальную общую базу для всех классов: интерфейс формы (без реализации) и конечные классы (полностью реализованные), проходящие через частично реализованные интерфейсы и четные интерфейсные кластеры, используя «доминирование» как диспетчеризацию от интерфейса до реализаций через «многоуровневую структуру». -параллелограмм "Схема наследования.
Сравнение ООП с java с С ++ при условии, что существует только один и единственный способ ООП, ограничивает возможности обоих языков.
Принуждение C ++ к строгому соблюдению идиом кодирования Java денатурирует C ++, так как принуждение Java вести себя как C ++ -подобный язык денатурирует Java.
Дело не в «чувствительности», а в разных «механизмах агрегации», которыми обладают два языка, и по-разному объединяют их, что делает некоторые идиомы более выгодными в одном языке, чем в другом, и наоборот.
источник
Принцип справедлив для обоих языков, но вы не проводите справедливое сравнение. Вы должны сравнить чистые абстрактные классы C ++ с интерфейсами Java.
Даже в C ++ у вас могут быть абстрактные классы, в которых реализованы некоторые функции, но они происходят от чистого абстрактного класса (без реализаций). В Java у вас будут те же абстрактные классы (с некоторыми реализациями), которые могут быть получены из интерфейсов (без реализаций).
источник
Как правило, те же принципы ОО верны для Java и C ++. Однако одно большое отличие состоит в том, что C ++ поддерживает множественное наследование, тогда как в Java вы можете наследовать только от одного класса. Это главная причина, по которой у Java есть интерфейсы, которые, я считаю, дополняют отсутствие множественного наследования и, возможно, ограничивают то, что вы можете с ним делать (так как много критики вызывает злоупотребление множественным наследованием). Так что, вероятно, по мнению программистов на Java, существует более сильное различие между абстрактными классами и интерфейсами. Абстрактные классы используются для совместного использования и наследования поведения, в то время как интерфейсы просто используются для добавления дополнительной функциональности. Помните, что в Java вы можете наследовать только от одного класса, но у вас может быть много интерфейсов. В C ++ , однако, чистые абстрактные классы (т.е. «C ++ интерфейс») являются используется для совместного использования и наследования поведения в отличие от цели интерфейса Java (хотя вам все еще необходимо реализовать функции), поэтому использование отличается от интерфейсов Java.
источник
Иногда имеет смысл иметь некоторую реализацию по умолчанию. Например, общий метод PrintError (string msg), который применим ко всем подклассам.
Это все еще может быть переопределено, если действительно необходимо, но вы можете сэкономить клиенту некоторые хлопоты, позволяя ему просто вызвать универсальную версию.
источник