Ответ 1
Несколько ключевых различий в стиле "Стиль" в расширенном баннере ООП.
Во всех случаях утверждение о системе статического или динамического типа означает преимущественно то или иное, проблема далека от четкого или четко определенного. Кроме того, многие языки выбирают размывание линии между выборами, поэтому это не список двоичных вариантов любым способом.
Полиморфное позднее связывание
или "что означает foo.Bar(x)
?"
- Иерархия типов сглажена для конкретной реализации на один экземпляр (часто делается с помощью vtable) и часто позволяет явно ссылаться на реализацию базовых классов,
- Концептуально вы смотрите на наиболее специфический тип, который foo находится на callsite. Если он имеет реализацию Bar для вызываемого параметра x, если не выбран родительский элемент foo и процесс повторяется.
- Примеры: С++/Java/С#, " Simula style" часто используется.
- Чистое сообщение. Код в foo, который обрабатывает сообщения с именем "Bar", просят принять x. Только имя имеет значение, а не какие-либо предположения, которые, возможно, имели место на сайте вызова, о том, что именно должен был быть Бар. Контрастность с предыдущим стилем, в котором рассматривался метод, известен как нечто определенное на всем, что было известно о иерархии типов, определенной во время компиляции (хотя точное место в иерархии осталось до времени исполнения).
- Примеры: Objective-C/Ruby, Smalltalk style" часто используется.
1 часто используется в статически типизированных фреймворках, где это ошибка, проверенная во время компиляции, чтобы такая реализация не существовала. Далее языки часто различают Bar (x) и Bar (y), если x и y - разные типы. Это перегрузка метода, и полученные методы с таким же именем рассматриваются как совершенно разные.
2 часто используется в динамических языках (которые, как правило, избегают перегрузки методов), поэтому возможно, что во время выполнения тип foo не имеет обработчика для сообщения с именем "Bar", разные языки обрабатывают это в разных пути.
Оба могут быть реализованы за кулисами тем же способом, если это необходимо (часто по умолчанию для второго, стиль Smalltalk должен вызывать функцию, но во всех случаях это не определяется определенным образом). Так как прежний метод часто может быть легко реализован как простые вызовы функции смещения указателя, он может быть легче сделан относительно быстро. Это не означает, что другие стили также не могут выполняться быстро, но при этом может потребоваться больше работы, чтобы гарантировать, что при этом не будет скомпрометирована большая гибкость.
Inheritance/Повторное использование
или "Откуда берутся дети?"
- Основанный на классе
- Реализации методов организованы в группы, называемые классами. Когда желательно наследование реализации, определяется класс, который расширяет родительский класс. Таким образом, он получает все открытые аспекты родителя (оба поля и методы) и может выбрать изменение определенных/всех этих аспектов, но не может удалить их. Вы можете добавлять и обновлять, но не удалять.
- Примеры: С++/Java/С# (обратите внимание, что и SmallTalk, и Simula используют это)
- Прототип основан на
- Любой экземпляр объекта представляет собой просто набор идентифицированных методов (обычно идентифицируемых по имени) и указывается в виде (снова названных) полей. Всякий раз, когда требуется новый экземпляр этого типа, существующий экземпляр можно использовать для клонирования нового. Этот новый класс сохраняет копию состояния и методов предыдущего класса, но затем может быть изменен для удаления, добавления или изменения существующих именованных полей и методов.
- Примеры: Self/JavaScript
Снова 1 имеет тенденцию происходить на статических языках, 2 в динамике, хотя это отнюдь не требование, которое они просто поддаются стилю.
Интерфейс или класс
или "что и как?"
- Интерфейсы перечисляют требуемые методы. Это контракт
- Примеры: VB6
- Методы списка классов, которые требуются, но могут необязательно поставлять их реализацию
- Примеры: Simula
Это не двоичный выбор. Большинство языков, основанных на классе, допускают концепцию абстрактных методов (те, которые еще не реализованы). Если у вас есть класс, в котором все методы являются абстрактными (называемый чистым виртуальным в С++), то то, что класс представляет собой, в значительной степени представляет собой интерфейс, хотя и тот, который, возможно, также определил некоторое состояние (поля). Истинный интерфейс не должен иметь никакого состояния (поскольку он определяет только то, что возможно, а не как это происходит.
Только более старые языки ООП, как правило, полагаются исключительно на то или другое.
VB6 имеет только интерфейсы и не имеет наследования реализации.
Simula позволяет вам объявлять чистые виртуальные классы, но вы можете создавать их (с ошибками во время использования)
Одиночное или множественное наследование
или "Кто такой папа?"
- Single
- Только один тип может быть родителем для другого. В вышеописанной форме Class вы можете расширить (принять реализацию) только один тип. Обычно эта форма включает концепцию интерфейсов в качестве первоклассных аспектов языка, чтобы компенсировать это.
- преимущества включают более чистые метаданные и интроспекцию, более простые языковые правила.
- осложнения включают затруднение приведения полезных методов в объем (такие как MixIns и методы расширения, чтобы уменьшить эту проблему)
- Примеры: С#/java
- Несколько - вы можете расширить несколько классов
- преимущества включают в себя определенные структуры, которые легче моделировать и проектировать.
- осложнения включают сложные правила разрешения конфликтов, особенно когда существуют перегруженные методы, которые могут принимать либо родительский тип.
- Примеры: С++/Eiffel
Этот вопрос вызывает значительную дискуссию, тем более что это ключевой отличительный признак между реализацией COP OOP и многими современными статически типизированными языками, воспринимаемыми как возможные преемники, такие как С# и java.
Изменчивость
или "что вы хотите сделать со мной?"
- Mutable
- Объекты, созданные после создания, могут изменить свое состояние.
- Imutable
- Объекты, созданные после создания, не могут быть изменены.
Часто это не все или ничего, это просто по умолчанию (обычно используемые языки OOP по умолчанию изменяются по умолчанию). Это может сильно повлиять на то, как язык структурирован. Многие в основном функциональные языки, включенные в функции ООП, по умолчанию имеют объекты, имеющие неизменяемое состояние.
"Перфективность" их ООП
или "Все ли объект?"
- Абсолютно все в системе рассматривается как объект (возможно, вплоть до самих методов, которые являются просто другим видом объекта и могут взаимодействовать таким же образом, как и другие объекты).
- Примеры: SmallTalk
- Не все это объект, вы не можете передавать сообщения ко всему (хотя система может перепрыгивать через обручи, чтобы они казались такими, как вы можете)
- Примеры: С++/С#/Java (см. примечание *)
Это довольно сложно, так как такие методы, как автоматическое боксирование примитивов, кажутся похожими на все, но вы обнаружите, что существует несколько граничных случаев, когда эта "магия компилятора" обнаружена, и пословичный волшебник из страны Оз находится за занавеской в результате проблемы или ошибки. В языках с неизменяемостью по умолчанию это менее вероятно, так как ключевой аспект объектов (который они содержат как методы, так и состояние) означает, что вещи, похожие на объекты, но не имеющие меньше возможностей для осложнений.
- В отношении Java/С# autoboxing (или в С#) позволяет обрабатывать синтаксически любую переменную, как если бы это был объект, но на самом деле это не так, и это проявляется в таких областях, как попытка блокировки объекта с автообъектом (отклоняется компилятором как это было бы очевидной ошибкой).
Статический или динамический
или "Кто вы такой, как вы думаете?"
Более распространенный аспект языкового дизайна, а не один, чтобы войти сюда, но выбор, присущий этому решению, влияет на многие аспекты ООП, как упоминалось ранее.
Просто аспекты полиморфного позднего связывания могут зависеть от:
- Тип объекта, которому передается сообщение (во время компиляции/времени выполнения)
- Тип параметра (s), которые передаются (во время компиляции/времени выполнения)
Чем более динамичный язык становится более сложным, эти решения, как правило, становятся, но наоборот, чем больше вводит пользователь языка, тем лучше, чем разработчик языка принимает решение. Приведя примеры здесь, можно было бы подумать о том, что безрассудно, поскольку статически типизированные языки могут быть изменены, чтобы включить динамические аспекты (например, С# 4.0).