Однажды я зашел в чат Stack Overflow и увидел фразу, в которой говорилось, что наследование, инкапсуляция и полиморфизм являются столпами ООП (в том смысле, что они являются фундаментальными, строительными подошвами).
Кроме того, есть аналогичный вопрос, который мне очень часто задавали на экзаменах в колледже и на собеседованиях, и правильным ответом всегда было утверждение, произнесенное в заголовке вопроса («Да, наследование, инкапсуляция и полиморфизм - это столпы ООП». ).
Но в чате Stack Overflow меня жестоко высмеивали, участники категорически не соглашались с таким утверждением. Итак, что не так с этим утверждением?
Кажется ли, что программисты обучаются разным вещам в постсоветских и американских колледжах?
Разве наследование, инкапсуляция и полиморфизм не считаются столпами ООП программистами из США / Великобритании?
источник
Ответы:
Многие программисты считают их столпами, и многие колледжи преподают ОО таким образом.
К сожалению, это также близорукий взгляд.
ООП имеет очень мало оснований, поскольку в действительности это очень концептуально: «Подход к дизайну вашей программы, думая о вещах как об объектах - связных пакетах данных и функциональности».
И в то время как современный дизайн программы плохо понимает, что нужно делать что-то «чисто ОО», большинство опытных программистов согласятся с тем, что принципы SOLID (или некоторое подмножество) являются более подходящими кандидатами для «столпов объектно-ориентированного программирования» (даже если они хорошо применять для не-ООП). Они не работают с этими условиями вообще. Вместо этого они используют понятия программных сущностей (из которых объекты являются одним), интерфейсов (из которых C # / Java / и т. Д.
interface
), Абстракции и подтипирования (из которых наследование является одной из форм).источник
tl; dr: Вы можете иметь наследование без OO, вы можете иметь инкапсуляцию без OO, вы можете иметь полиморфизм без OO, вы даже можете иметь все три сразу без OO. С другой стороны, вы можете иметь ОО без наследования. Кроме того, существуют различные виды инкапсуляции (ADT-ориентированные и OO), поэтому не всякая инкапсуляция является OO.
Длинная версия:
Термин «объектно-ориентированное программирование» был придуман Аланом Кейем, поэтому он решает, что это значит. И он определяет это так :
С точки зрения реализации, обмен сообщениями - это вызов процедур с поздней привязкой, и если вызовы процедур с поздней привязкой, вы не можете знать во время разработки Что касается что вы собираетесь вызывать, поэтому вы не можете делать какие-либо предположения о конкретном представлении состояния. Итак, на самом деле речь идет об обмене сообщениями, позднее связывание является реализацией обмена сообщениями, а инкапсуляция является следствием этого.
Позже он пояснил, что « большая идея -« обмен сообщениями » », и сожалеет, назвав его «объектно-ориентированным» вместо «ориентированного на сообщения», потому что термин «объектно-ориентированный» акцентирует внимание на неважной вещи (объектах). ) и отвлекает от того, что действительно важно (обмен сообщениями):
(Конечно, сегодня большинство людей даже не фокусируются на предметах, а на классах, что еще более неправильно).
Обмен сообщениями является основополагающим для ОО, как метафора и как механизм.
Если вы отправляете кому-то сообщение, вы не знаете, что они с ним делают. Только вещь , которую вы можете наблюдать, их ответ. Вы не знаете, обрабатывали ли они сообщение сами (т. Е. Если у объекта есть метод), пересылали ли они сообщение кому-либо еще (делегирование / передача), даже если они его понимали. Вот что такое инкапсуляция, вот что такое OO. Вы даже не можете отличить прокси от реального, пока он отвечает так, как вы ожидаете.
Более «современным» термином для «обмена сообщениями» является «динамическая диспетчеризация метода» или «вызов виртуального метода», но он теряет метафору и фокусируется на механизме.
Подобные пункты также в On Понимание абстракции данных, Revisited по Уильям Р. Кук , а также его предложение по упрощению, современные определения «объекта» и «объектно - ориентированного» .
В Smalltalk-72 не было даже никаких объектов! Были только потоки сообщений, которые были проанализированы, переписаны и перенаправлены. Сначала появились методы (стандартные способы анализа и перенаправления потоков сообщений), затем появились объекты (группы методов, которые разделяют некоторые частные состояния). Наследование появилось намного позже, и классы были введены только как способ поддержки наследования. Если бы исследовательская группа Кея уже знала о прототипах, они, вероятно, никогда бы не представили классы.
Каждый программист должен прочитать « Понимание абстракции данных» . Подробно объясняется, в чем именно разница между объектами и абстрактными типами данных. Он приводит примеры с использованием Java, и это чрезвычайно важно для этого вопроса, потому что и в примерах ADT, и в примерах Object он использует наследование, инкапсуляцию и полиморфизм, но только один из примеров является объектно-ориентированным! Другими словами: вы можете иметь наследование, инкапсуляцию и полиморфизм, вы даже можете иметь все три сразу и при этом не иметь ОО.
С другой стороны, вы можете иметь ОО без наследования. Как я намекал выше: оригинальные версии Smalltalk (язык, разработанный Аланом Кей, изобретателем термина «объектно-ориентированное программирование») не имели наследования.
Наконец, но не в последнюю очередь, в Орландском договоре обсуждается делегирование как альтернатива наследования и то, как различные формы делегирования и наследования приводят к различным точкам проектирования в пространстве разработки объектно-ориентированных языков. (Обратите внимание, что на самом деле даже в языках, которые поддерживают наследование, таких как Java, людей фактически учат избегать его, снова указывая на то, что оно не является необходимым для ОО.)
источник