Нужны ли нам ОО-языки для управления сложностью программного обеспечения?


209

Это будет очень нетехнический, мягкий вопрос, и я не уверен, что это правильная платформа. Но я начинающий студент CS, поэтому надеюсь, что вы, ребята, это терпите.

В первом семестре мы познакомились с такими понятиями ООП, как инкапсуляция, сокрытие данных, модульность, наследование и т. Д. Через Java и UML. (Java - мой первый язык программирования)

Насколько я понимаю, ООП - это способ управления сложностью программного обеспечения. Но его принципы не новы и не уникальны, они в некотором смысле универсальны для всех областей техники.

Например, автомобиль - это очень сложная структура, сложностью которой управляет иерархия модульных и инкапсулированных компонентов с четко определенным поведением и интерфейсами.

Но я не понимаю причину введения новой парадигмы программирования. Я думаю, что все принципы, используемые для управления сложностью, могут быть реализованы с помощью процедурных языков программирования. Например, для модульности мы можем просто разделить программу на множество небольших программ, которые выполняют четко определенные задачи, код которых содержится в отдельных файлах. Эти программы будут взаимодействовать друг с другом через их четко определенный ввод и вывод. Файлы могут быть защищены (зашифрованы?) Для достижения инкапсуляции. Для повторного использования кода мы можем просто вызывать эти файлы всякий раз, когда они нужны в новых программах. Разве это не отражает все, что такое ООП, или я упускаю что-то очень очевидное?

Я не прошу доказательств того, что ООП управляет сложностью. На мой взгляд, это действительно так. Но я думаю, что все принципы, используемые для управления сложностью, такие как модульность, инкапсуляция, скрытие данных и т. Д., Могут быть легко реализованы процедурными языками. Так зачем же ООП, если мы можем управлять сложностью без нее?


41
Вам не хватает разделения интерфейса и реализации. Возможность поменять одну реализацию на другую во время выполнения - очень важная особенность. По сути, это достигается динамическим методом диспетчеризации ОО-языков с наследованием. Процедурные языки тоже могут это делать (читай: пустые указатели), но без безопасности типов.
Марстато

81
В значительной степени идея объектно-ориентированных языков и дизайна состоит именно в том, чтобы сделать эти универсальные, интуитивно понятные концепции как можно проще для представления и воссоздания в коде. Если бы у вас была схема или набор руководящих принципов для достижения всех этих целей без изначально объектно-ориентированного языка, тогда ваши предложения о том, как действовать, будут эффективно использоваться объектно-ориентированной методологией. Фактические ОО-языки - это просто способ формализовать и упростить это.
Резерв

14
@RobbieDee ты на самом деле читал мой вопрос? Речь идет о попытке понять ОО на более фундаментальном уровне, задавая вопрос о том, можно ли управлять сложностью программного обеспечения без ОО. Я не пытаюсь подорвать ОО, не пытаюсь изобрести что-то новое, я просто пытаюсь понять это лучше, и если вопрос настолько «самоочевиден», почему он получил отличный ответ от Йорга?
steakexchange

12
Шифрование файла не является инкапсуляцией. Возможно, вы скрыли содержимое кода от другого разработчика, но вы не обязательно защитили внутреннюю работу кода от другого кода. Оригинальный автор мог сделать это до или после шифрования, если он может вспомнить, как.
JeffO

8
Вам не нужно ничего, кроме машинного языка - пусть программист запомнит коды операций и сам напишет их и нули. Но наличие своего рода «символического» языка очень полезно с точки зрения уменьшения ошибок и повышения производительности, и, как заметил Дейкстра, язык, который навязывает некоторую «структуру» (или, по крайней мере, облегчает поддержание «структуры»), помогает значительно. ОО-языки, возможно, не являются идеальной технологией, учитывая текущий уровень сложности языка, но они довольно хороши для многих приложений. Идея состоит в том, чтобы управлять сложностью, не мешая.
Даниэль Р Хикс

Ответы:


177

Позвольте мне попробовать с очень низким теоретическим ответом :)

Что вы действительно спрашиваете: зачем включать поддержку Object Orientation (OO) непосредственно в язык, когда процедурные языки могут использоваться для разработки и написания OO-кода?

И ответ таков: иметь стандарт того, как ОО выражается в исходном коде, чтобы у вас не было 22 разных реализаций для одной и той же абстракции.

Например, допустим, я создал а MagicButtonи а, MagicSliderкоторые можно использовать в системе пользовательского интерфейса. Мне нужен способ сгруппировать методы, которые можно использовать с MagicButton, методы, которые можно использовать только с MagicSlider, и методы, которые могут использоваться обоими. Эти объекты имеют несколько общих методов, потому что они оба являются объектами Magic gui.

Я могу выполнить группировку, назвав функции особым образом MagicSlider_DoSomething ..., включив методы в определенные файлы, названные особым образом MagicSliderMethods.XXX, или я мог бы найти какой-то другой особый способ сделать то же самое. Если в языке не существует стандартного способа сделать это, я сделаю это не так, как вы, и не так, как кто-либо другой. Это делает совместное использование кода намного сложнее.

Да, поздняя диспетчеризация - виртуальные методы на ОО-языках - может быть реализована на процедурных языках, но существует много разных способов ее реализации. В зависимости от того, кто написал код, вы получите разные реализации ОО внутри одной и той же программы.

Подумайте о плохом разработчике обслуживания. Этот человек должен управлять различными абстракциями объектов и разными способами вызывать виртуальные методы в зависимости от того, кто написал исходный код.

Также: Наличие абстракций в языке позволяет продвинутым редакторам кода, таким как Eclipse, выполнять большой статический анализ кода. Например, Eclipse может предложить список всех методов, которые могут использоваться на объекте, а также автоматическую реализацию пустых «методов TODO». Eclispe точно знает, какие методы должен реализовывать ваш класс, основываясь на том, какие классы вы расширяете и какие интерфейсы вы реализуете. Это было бы почти невозможно, если бы не было языкового стандарта для ОО.


40
Классический пример: Lua. Это не изначально ОО, но может быть сделано, но это означает, что есть около 5 различных одинаково хорошо известных ОО-библиотек, которые не полностью совместимы.
Kroltan

55
@steakexchange Вы слишком много внимания уделяете абсолютам. У очень немногих есть «единственная цель». Языки все делают много разных вещей с разной степенью качества. Выбор языка - это выбор компромиссов, которые делают его наиболее подходящим для той цели, для которой он вам нужен.
Тим Б

42
@nocomprende Стандартизация абстракций - это буквально то, для чего нужны языки программирования. Даже ассемблерный язык абстрагируется от различий между десятью поколениями оборудования за полтора десятилетия.
Дэвид

56
@DavidMoles Стандартизированные абстракции - это буквально языки программирования. Не упустите прекрасную возможность использовать «буквально» буквально!
Клемент

12
Это можно стандартизировать. Когда я был в университете в середине 90-х, я проделал довольно значительную работу в X-Windows (в основном на основе Motif для тех, кто помнит такие вещи). X-Windows действительно позволяет реализовать все возможности ориентации объекта в обычном C . Ментальная гимнастика, чтобы сделать это, была довольно существенной, хотя и в значительной степени зависела от людей, не заглядывающих внутрь коробки (в этот момент Кодекс Шредингера вообще заканчивался мертвым). ОО-языки скрывают это от программистов так же, как это делает обычный компилятор для ассемблера, и жизнь становится проще.
Грэм

211

В первом семестре мы познакомились с такими понятиями ООП, как инкапсуляция, сокрытие данных, модульность, наследование и т. Д. Через Java и UML. (Java - мой первый язык программирования)

Ни одна из этих концепций ООП. Все они существуют вне ОО, независимо от ОО, и многие даже были изобретены до ОО.

Итак, если вы думаете , что что то , что OO это все о, то ваш вывод прав: вы можете сделать все из тех , на процедурных языках, потому что они не имеют ничего общего с ОО .

Например, одна из основополагающих статей о модульности - «Критерии для использования при разложении систем на модули» . Там нет упоминания о OO там. (Он был написан в 1972 году, к тому времени ОО все еще оставалась неясной нишей, хотя ему уже более десяти лет.)

Хотя абстракция данных важна в ОО, она является скорее следствием основной функции ОО (обмена сообщениями), чем определяющей. Кроме того, очень важно помнить, что существуют различные виды абстракции данных. Два наиболее распространенных вида абстракции данных, используемых сегодня (если мы игнорируем «никакой абстракции вообще», которая, вероятно, все еще используется больше, чем два других вместе взятых), это Абстрактные типы данных и объекты . Итак, просто говоря «сокрытие информации», «инкапсуляция» и «абстракция данных», вы ничего не сказали об ОО, поскольку ОО - это всего лишь одна из форм абстракции данных, и эти два на самом деле принципиально различны:

  • В случае абстрактных типов данных механизмом абстракции является система типов ; это система типов, которая скрывает реализацию. (Система типов не обязательно должна быть статичной.) В объектах реализация скрыта за процедурным интерфейсом , который не требует типов. (Например, это можно реализовать с помощью замыканий, как это делается в ECMAScript.)
  • В случае абстрактных типов данных экземпляры разных ADT инкапсулированы друг в друга, но экземпляры одного ADT могут проверять и получать доступ к представлению и частной реализации друг друга. Объекты всегда изолированы от всего . Только объект сам может проверить свое собственное представительство и доступ к собственным реализации. Никакой другой объект , даже другие объекты того же типа, другие экземпляры того же класса, другие объекты, имеющие тот же прототип, клоны объекта или что-либо еще, могут это сделать. Никто .

Кстати, это означает, что в Java классы не являются объектно-ориентированными. Два экземпляра одного класса могут получить доступ к представлению друг друга и частной реализации. Поэтому экземпляры классов не являются объектами, а фактически являются экземплярами ADT. Java interfaces, однако, действительно обеспечивают объектно-ориентированной абстракции данных. Итак, другими словами: только экземпляры интерфейсов являются объектами в Java, экземпляры классов - нет.

В основном, для типов вы можете использовать только интерфейсы. Это означает, что типы параметров методов и конструкторов, типы возвращаемых методов, типы полей экземпляров, статические поля и локальные поля, аргумент instanceofоператора или оператора приведения и аргументы типа для конструктора универсального типа всегда должны быть интерфейсами. Класс может использоваться только сразу после newоператора, нигде больше.

Например, для модульности мы можем просто разделить программу на множество небольших программ, которые выполняют четко определенные задачи, код которых содержится в отдельных файлах. Эти программы будут взаимодействовать друг с другом через их четко определенный ввод и вывод. Файлы могут быть защищены (зашифрованы?) Для достижения инкапсуляции. Для повторного использования кода мы можем просто вызывать эти файлы всякий раз, когда они нужны в новых программах. Разве это не отражает все, что такое ООП, или я упускаю что-то очень очевидное?

То, что вы описываете, является OO.

Это действительно хороший способ думать о ОО. Фактически, это именно то, что имели в виду первоначальные изобретатели ОО. (Алан Кей пошел еще дальше: он предполагал, что множество маленьких компьютеров посылают сообщения друг другу по сети.) То, что вы называете «программой», обычно называется «объектом», и вместо «звонка» мы обычно говорим «отправить сообщение». ».

Ориентация на объект - это все об обмене сообщениями (он же динамическая диспетчеризация ). Термин «Объектно-ориентированный» был придуман доктором Аланом Кей, главным разработчиком Smalltalk, и он определяет его так :

Для меня ООП означает только обмен сообщениями, локальное хранение и защиту, а также скрытие процесса состояния и крайнюю позднюю привязку всех вещей.

Давайте разберемся с этим:

  • обмен сообщениями («отправка виртуального метода», если вы не знакомы с Smalltalk)
  • государственный процесс должен быть
    • локально сохраняется
    • защищенный
    • скрытый
  • крайняя поздняя привязка всех вещей

С точки зрения реализации обмен сообщениями - это вызов процедур с поздней привязкой, и если вызовы процедур связаны с поздней привязкой, вы не можете знать во время разработки, что вы собираетесь вызывать, поэтому вы не можете делать какие-либо предположения о конкретном представлении состояния. Итак, на самом деле речь идет об обмене сообщениями, позднее связывание является реализацией обмена сообщениями, а инкапсуляция является следствием этого.

Позже он пояснил, что « большая идея - это« обмен сообщениями » », и сожалеет, назвав его «объектно-ориентированным» вместо «ориентированного на сообщения», потому что термин «объектно-ориентированный» акцентирует внимание на неважной вещи (объектах). ) и отвлекает от того, что действительно важно (обмен сообщениями):

Просто мягкое напоминание о том, что на последней OOPSLA я приложил некоторые усилия, чтобы напомнить всем, что Smalltalk - это не только НЕ синтаксис или библиотека классов, но даже не классы. Мне жаль, что я давно придумал термин «объекты» для этой темы, потому что он заставляет многих людей сосредоточиться на меньшей идее.

Основная идея - «обмен сообщениями» - вот что является ядром Smalltalk / Squeak (и это то, что никогда не было полностью завершено на нашей фазе Xerox PARC). У японцев есть маленькое слово - ma - для «того, что находится между» - возможно, ближайший английский эквивалент - «interstitial». Ключом к созданию великолепных и расширяемых систем является гораздо больше, чем дизайн их модулей, а не их внутренние свойства и поведение. Подумайте об Интернете - чтобы жить, он (а) должен позволять множество различных видов идей и реализаций, выходящих за рамки какого-либо единого стандарта, и (б) обеспечивать различные степени безопасного взаимодействия между этими идеями.

(Конечно, сегодня большинство людей даже не сосредотачиваются на предметах, а на классах, что еще более неправильно).

Обмен сообщениями является фундаментальным для ОО, как метафора и как механизм.

Если вы отправляете кому-то сообщение, вы не знаете, что они с ним делают. Только вещь , которую вы можете наблюдать, их ответ. Вы не знаете, обрабатывали ли они сообщение сами (т. Е. Если у объекта есть метод), пересылали ли они сообщение кому-либо еще (делегирование / передача), даже если они его понимали. Вот что такое инкапсуляция, вот что такое OO. Вы даже не можете отличить прокси-сервер от реального, если он отвечает так, как вы ожидаете.

Более «современным» термином для «обмена сообщениями» является «динамическая диспетчеризация метода» или «вызов виртуального метода», но он теряет метафору и фокусируется на механизме.

Итак, есть два способа взглянуть на определение Алана Кея: если вы посмотрите на него, стоящее само по себе, вы можете заметить, что обмен сообщениями - это в основном вызов процедуры с поздней привязкой, а поздняя привязка подразумевает инкапсуляцию, поэтому мы можем заключить, что # 1 и # 2 на самом деле являются избыточными, а OO - все о позднем связывании.

Однако позже он пояснил, что важной вещью является обмен сообщениями, и поэтому мы можем взглянуть на него под другим углом зрения: обмен сообщениями связан с запозданием. Теперь, если бы обмен сообщениями был единственно возможным, тогда №3 был бы тривиально верным: если есть только одна вещь, и эта вещь связана с опозданием, то все вещи связаны с опозданием. И снова, инкапсуляция следует из обмена сообщениями.

Подобные замечания также делаются в « Об понимании абстракции данных», вновь рассмотренном Уильямом Кук, а также в его предложении по упрощенным, современным определениям «Объект» и «Объектно-ориентированный» :

Динамическая диспетчеризация операций является существенной характеристикой объектов. Это означает, что вызываемая операция является динамическим свойством самого объекта. Операции не могут быть идентифицированы статически, и в общем случае невозможно точно знать, какая операция будет выполнена в ответ на данный запрос, кроме как при ее запуске. Это точно так же, как с первоклассными функциями, которые всегда отправляются динамически.

В Smalltalk-72 даже не было никаких объектов! Были только потоки сообщений, которые были проанализированы, переписаны и перенаправлены. Сначала появились методы (стандартные способы анализа и перенаправления потоков сообщений), затем появились объекты (группы методов, которые разделяют некоторые частные состояния). Наследование появилось намного позже, и классы были введены только как способ поддержки наследования. Если бы исследовательская группа Кея уже знала о прототипах, они, вероятно, никогда бы не представили классы.

Бенджамин Пирс в « Типах и языках программирования» утверждает, что определяющей чертой объектно-ориентации является открытая рекурсия .

Итак, по словам Алана Кея, OO - это все о сообщениях. По словам Уильяма Кука, ОО - это динамическая диспетчеризация методов (что на самом деле одно и то же). По словам Бенджамина Пирса, OO - это все об открытой рекурсии, что в основном означает, что самореференции динамически разрешаются (или, по крайней мере, так думают), или, другими словами, обмениваются сообщениями.

Как видите, человек, который придумал термин «ОО», имеет довольно метафизический взгляд на объекты, Кук - довольно прагматичный взгляд, а Пирс - очень строгий математический взгляд. Но важно то, что философ, прагматик и теоретик все согласны! Обмен сообщениями является одним из столпов ОО. Период.

Обратите внимание, что здесь нет упоминания о наследовании! Наследование не обязательно для ОО. В общем, большинство ОО-языков имеют некоторый способ повторного использования реализации, но это не обязательно должно быть наследованием. Это также может быть, например, некоторая форма делегирования. Фактически, в Орландском договоре делегирование рассматривается как альтернатива наследования, и как различные формы делегирования и наследования приводят к различным точкам проектирования в пространстве проектирования объектно-ориентированных языков. (Обратите внимание, что на самом деле даже в языках, которые поддерживают наследование, таких как Java, людей фактически учат избегать его, снова указывая на то, что оно не нужно для ОО.)


16
+100 - Мы возлагаем вину на вещи, потому что они используются ненадлежащим образом.
Джефф

55
Извините, но это невероятно неправильно. Алан Кей, возможно, придумал этот термин, но принципы существовали еще до Smalltalk. Объектно-ориентированное программирование происходит от Simula, а его ОО-стиль не имеет ничего общего с «сообщениями». Практически каждый успешный ОО-язык работал на базовых принципах, изложенных в Simula - те же, что мы видим в Java - и ООП в стиле Smalltalk был провалом на «рынке идей» каждый раз, когда его вводили снова, потому что это просто не очень хорошо работает. Имя было единственной действительно значимой вещью, которую внес Кей.
Мейсон Уилер,

23
@steakexchange Нет. «Сущность ОО», то, что делает его действительно отличительным, - это объекты с виртуальными методами. Есть причина, по которой никто не использует Smalltalk: система передачи сообщений очень плохо работает в масштабах отдельных компьютеров. Каждый раз, когда какой-то доброжелательный, но наивный разработчик языка пытается переопределить принципы Smalltalk, он терпит неудачу. (Самым последним примером был бы Objective-C, который никто бы никогда не использовал, если бы Стив Джобс не сдвинул его с мертвой точки всему сообществу iOS. Он никогда не находил никаких преимуществ за пределами экосистемы Apple, и для этого есть причина. )
Мейсон Уилер

28
@MasonWheeler Не могли бы вы уточнить свой комментарий в ответе, поскольку у вас совершенно противоположное мнение о том, что говорит Йорг?
steakexchange

20
Стоит также отметить, что концепция объектно-ориентированных языков сильно изменилась. Эти предковые концепции могут быть не такими верными в наши дни, когда множество языков отбрасывают старые модели и принимают мультипарадигмы. Посмотрите, например, на C # - этот язык смешивает почти все под солнцем одновременно и, хотя его называют в основном ОО-языком, на самом деле он представляет собой смесь различных парадигм. Это позволяет ему быть действительно выразительным инструментом для разработчиков по всему миру. Кроме того, ОО на основе классов является одним из многих в равной степени действительных разновидностей ОО-программирования.
Т. Сар

66

Но я думаю, что все принципы, используемые для управления сложностью, такие как модульность, инкапсуляция, скрытие данных и т. Д., Могут быть легко реализованы процедурными языками.

Когда вы говорите «очень легко», вы делаете очень смелое заявление. Я читаю это так: «Я не вижу трудности, поэтому она не должна быть очень большой». Если сформулировать это таким образом, становится ясно, что вы не спрашиваете «зачем нам нужен ОО», а спрашиваете: «Почему трудности, с которыми столкнулись другие программные парадигмы, которые приводят к изобретению ОО, сразу не очевидны для меня? "

Ответ на этот вопрос заключается в том, что многие из этих трудностей не существуют в тех программах, над которыми вы работаете. Вас не просят обновить 40-летний код спагетти. Вы не пытаетесь написать новый диспетчер отображения для операционной системы. Вы не отлаживаете многопоточные распределенные приложения.

Для многих игрушечных программ, которые мы, ученики CS, ставим перед собой задачей, мы могли бы писать их на бейсике или ассемблере так же, как на Java или Python. Это связано с тем, что сложность задач настолько низка, что существует только один разработчик, нет проблем с функциональной совместимостью, производительность не имеет значения, и код, скорее всего, будет запускаться лишь несколько раз на одной машине.

Представьте себе, что вы берете студенческого водителя и просите его в час пик выехать на оживленную улицу на механической коробке передач без синхронной сетки, направляясь к крутому склону. Катастрофа. Почему? Они не могут управлять уровнем сложности, необходимым для одновременного следования всем правилам, необходимым для этой задачи.

А теперь представьте того же студента, ту же машину, которая едет в шаговой доступности на пустой стоянке. Они в порядке, потому что их уровень мастерства соответствует задаче. Нет никакого давления, небольшого риска, и они могут взять на себя отдельные подзадачи запуска, сцепления, переключения, ускорения, рулевого управления по одному.

Этот студент может спросить, почему у нас автоматические коробки передач, если опытный водитель может делать все эти вещи одновременно? Ответ в том, что достаточно опытный водитель в оптимальных условиях не нуждается в автомате. Но мы не все профессиональные водители в отличном состоянии, и мы обычно хотим, чтобы дизайнеры автомобиля позаботились обо всей этой сложности для нас.

Опытный, достаточно дисциплинированный программист действительно может создать функционирующую систему высокой сложности на C или сборке. Но мы не все Линус Торвальдс. Мы также не должны создавать полезное программное обеспечение.

Лично я не заинтересован в том, чтобы заново изобретать все возможности современного языка, прежде чем я смогу решить проблему. Если я могу воспользоваться языком, который включает в себя решения уже решенных проблем, то почему бы и нет?

Поэтому я переверну ваш вопрос и задам вопрос: если языки предоставляют удобные функции, такие как инкапсуляция и полиморфизм, почему бы нам не использовать их?


13
Таким образом, в основном можно сделать ОО с процедурным языком, но это делает вещи вручную, в то время как использование стандартизированного языка ОО автоматизирует и упрощает.
steakexchange

6
@steakexchange В значительной степени именно это.
Тим Б

3
@steakexchange хорошим историческим примером этого была объектная модель для X Windows в те времена. Он был написан на C, но был основан на объектно-ориентированной системе. Таким образом, вы должны были следовать определенным соглашениям, чтобы взаимодействовать с ним, чтобы ваши классы играли хорошо со всеми остальными.
Ukko

7
@nocomprende Конечно. Но можно сделать компьютер неспособным к загрузке, выполняя необработанные операции записи на диск вместо того, чтобы полагаться на файловую систему, и будет действительно трудно отлаживать проблемы в специальной объектной системе, созданной новичком. Инкапсуляция, если все сделано правильно, удерживает нас от намеренного или непреднамеренного вмешательства в то, что мы не должны.
Клемент

3
Мне интересно, что примеры, которые вы даете о приложениях, которые выиграют от ОО, часто не написаны на ОО-языках. Спагетти 40 лет, скорее всего, написаны на C, COBOL, FORTRAN или REXX. Диспетчер отображения, скорее всего, написан на C (хотя и с соглашениями OO-ish), и многие успешные распределенные многопоточные системы написаны на Erlang, Go или C.
James_pic

22

То, что вы описываете, это не ООП, а абстракция. Абстракция присутствует во всех современных моделях дизайна, даже тех, которые не являются ООП. А ООП - это очень специфический вид абстракции.

Во-первых, стоит отметить, что не существует единого определения ООП, поэтому могут быть люди, которые не согласны с тем, что я называю ООП.

Во-вторых, важно помнить, что ООП вдохновлялись традиционными моделями дизайна, поэтому сходство с дизайном автомобиля не случайно.

Тем не менее, вот несколько способов, которыми ООП имеет больше нюансов, чем вы сказали:

  • Инкапсуляция: речь идет не только о наличии установленного интерфейса для модуля (то есть абстракции), но и о запрете доступа за пределы этого интерфейса. В Java доступ к закрытой переменной является ошибкой компиляции, в то время как в вашей машине вы можете (в некоторых случаях) использовать вещи, которые отличаются от намеченного интерфейса.

  • Наследование: это действительно то, что делает ООП уникальным. После того как вы определили интерфейс, вы можете сделать несколько вещей, реализующих этот интерфейс, и вы можете сделать это иерархическим способом, изменяя определенные части их реализации, в то же время наследуя все предыдущие части, что значительно сокращает дублирование кода.

    Если вы думаете с точки зрения инкапсулированных компонентов автомобиля, на самом деле нет эквивалента этому. У меня нет способа сделать механизм, выбрав другой механизм и изменив конкретную часть его реализации. (По крайней мере, я так не думаю, я не знаю много об автомобилях).

  • Полиморфизм . После того, как вы определили интерфейс, все, что использует этот интерфейс, должно быть неразличимо с точки зрения доступных операций, и вам не нужно знать, какая реализация используется для использования интерфейса. Именно здесь становятся важными подтипы и принцип подстановки Лискова .

  • Связь : ключевым аспектом ООП является то, что мы тесно связываем вещи с одинаковыми операциями и распространяем различные формы, которые они могут иметь. Данные связаны с операциями с этими данными. Это означает, что очень легко добавить новую форму данных (новую реализацию), но очень трудно добавить новую операцию в интерфейс (поскольку вам придется обновлять каждый класс, который реализует интерфейс). Это отличается от алгебраических типов данных в функциональных языках, где очень легко добавить новую операцию (вы просто пишете функцию, которая обрабатывает все случаи), но сложно добавить новый вариант (так как вам нужно добавить новый дело для всех ваших функций).


1
Хороший ответ! С одной частью, с которой я не согласен: различие, которое вы проводите в отношении инкапсуляции, недействительно. Инкапсуляция всегда означает «запрещение доступа за пределы этого интерфейса» - это верно как для параметров OOP, так и для параметров, не относящихся к OOP. Так что эта часть на самом деле не уникальна для ООП.
DW

@WW Я попытался прояснить это, сказав не то, что это уникально для ООП, а в том, что это разница между инкапсуляцией и абстракцией. Спасибо за ответ!
17

2
ХОРОШО. Но у меня все еще есть другое мнение о том, что здесь написано на эту тему. Вы писали, что «вот несколько способов, с помощью которых ООП имеет больше нюансов, чем то, что вы сказали», но инкапсуляция не означает, что ООП имеет больше нюансов, чем написано в вопросе. Инкапсуляция - это то, что есть в любой парадигме. И когда вы написали, что «То, что вы описываете, это не ООП, это абстракция», я подумал, что оригинальный вопрос пытался описать инкапсуляцию (а не просто абстракцию). Я думаю, я просто оставлю этот комментарий с другой точки зрения. Я думаю, что ответ очень полезен!
DW

Наследование - это общая черта, но в некоторых важных языках OO его нет.
Брэд Сзонье

Хороший ответ, но IMO вы преувеличиваете пример автомобиля. Двигатель для данной модели имеет четко определенный интерфейс (кулачковый вал, монтажные кронштейны «розетки» и т. Д.). Вы можете заменить обычный старый карбюратор на впрыск топлива, добавить турбонагнетатель и т. Д., Не влияя на трансмиссию. (Хотя для дизельного двигателя требуется модифицированный топливный бак IIRC.) И наоборот, вы можете заменить механическую коробку передач на автоматическую и AFAIK, которая вообще не влияет на двигатель.
Дэвид

11

Нужны ли нам ОО-языки для управления сложностью программного обеспечения?

Это зависит от значения слова «необходимость».

Если «нужно» значит требует, то нет, мы этого не требуем.

Если «необходимость» означает «дает сильные выгоды», то я бы сказал: «Да», мы этого желаем.

Большая фотография

ОО-языки связывают функциональность с данными.

Вы можете избежать этой привязки и написать функции, которые передают значения данных.

Но тогда вы, вероятно, столкнетесь с совокупностями данных, которые собираются вместе, и вы начнете передавать кортежи, записи или словари данных.

И действительно, вот и все вызовы методов: частичные функции на связанных наборах данных.

Функция за функцией

Особенности ООП:

  • Наследование позволяет повторно использовать код (миксины) и концепт (абстрактные базовые классы / интерфейсы) - но вы можете получить это, переопределив функции и переменные в под-области видимости.
  • Инкапсуляция позволяет скрывать информацию, поэтому мы можем работать на более высоких уровнях абстракции - но вы можете сделать это с заголовочными файлами, функциями и модулями.
  • Полиморфизм позволяет нам использовать аргументы разных типов, если эти аргументы поддерживают одни и те же интерфейсы - но мы можем сделать это и с функциями.

Однако ни одна из этих вещей не происходит так легко, как с объектно-ориентированным языком с первоклассной поддержкой этих функций.

Рекомендации

Есть много критиков ООП .

Тем не менее, исследования показывают, что мы получаем большую производительность труда программистов от повторного использования кода через ООП. Это спорный вывод, и некоторые исследователи говорят, что они не могут воспроизвести этот прирост производительности, учитывая определенные ограничения. (источник)

Заключение

Нам не «нужен» ООП. Но в некоторых случаях пользователь хочет ООП.

Насколько я понимаю, зрелые программисты могут быть весьма продуктивными в объектно-ориентированном стиле. А когда пакеты имеют базовые объекты с простыми и понятными интерфейсами, даже новые программисты могут быстро стать достаточно продуктивными.


10

Я постараюсь быть краток.

Основным принципом ОО является сочетание данных и поведения в одной организационной единице (объекте).

Это то, что позволяет нам контролировать сложность, и когда она появилась, это была довольно инновационная концепция. Сравните это с файлами с одной стороны (чистые данные), программами, которые читают и обрабатывают эти файлы с другой стороны (чистая логика) и выводят (снова чистые данные).

Только собрав вместе этот пакет данных и логику, смоделировав какую-то сущность реального мира, вы можете начать обмениваться сообщениями, создавать дочерние классы, отделять частные данные от общедоступных данных и поведения, реализовывать полиморфное поведение и выполнять всю эту специфическую для ОО магию.

Так что да, ОО имеет большое значение. И нет, это не просто куча старых вещей с причудливым названием.

Разобрав все это на части, взглянув на элементы, а затем сказав: «О, ну, здесь ничего такого, чего я раньше не видел», - это не признание сборки, которая содержит инновации. Результат больше, чем сумма его частей.


8

Не существует «официального» определения объектно-ориентированного программирования, и разумные люди не согласны с тем, что на самом деле определяет качество ОО. Некоторые говорят, что обмен сообщениями, некоторые говорят о подтипах, некоторые говорят о наследовании, другие говорят о связывании данных и поведения. Это не означает, что этот термин не имеет смысла, просто вы не должны слишком увлекаться спорами о том, что такое настоящий ОО.

Инкапсуляция и модульность являются более фундаментальными принципами проектирования и должны применяться во всех парадигмах программирования. Сторонники ОО не утверждают, что эти свойства могут быть достигнуты только с ОО - только то, что ОО особенно хорошо подходит для достижения этой цели. Конечно, сторонники других парадигм, таких как, скажем, функциональное программирование, утверждают то же самое для своей парадигмы. На практике многие успешные языки являются мультипарадигмальными, и ОО, функциональные и т. Д. Должны рассматриваться как инструменты, а не как «один верный путь».

Я думаю, что все принципы, используемые для управления сложностью, могут быть реализованы с помощью процедурных языков программирования.

Правда, потому что в итоге вы можете делать что угодно на любом языке программирования. В некоторых языках это может быть проще, чем в других, поскольку все языки имеют свои сильные и слабые стороны.


7

Что-то, что другие ответы не упомянули: состояние.

Вы говорите об ОО как инструменте управления сложностью . В чем сложность? Это нечеткий термин. У всех нас есть это гештальтовое ощущение того, что это значит, но это сложнее понять. Мы могли бы измерить цикломатическую сложность, то есть количество путей выполнения кода, но я не знаю, о чем мы говорим, когда используем ОО для управления сложностью.

Я думаю, что мы говорим о сложности, связанной с состоянием.

В основе инкапсуляции лежат две основные идеи . Один из них, скрытие деталей реализации , довольно хорошо освещен в других ответах. Но другой скрывает свое состояние во время выполнения . Мы не копаемся с внутренними данными объектов; мы передаем сообщения (или вызываем методы, если вы предпочитаете детали реализации, а не концепцию, как указал Йорг Миттаг). Почему?

Люди уже упоминали, что это потому, что вы не можете изменить внутреннюю структуру ваших данных, не изменив код доступа к ним, и вы хотите сделать это в одном месте (метод доступа) вместо 300 мест.

Но это также потому, что это делает код трудным для рассуждения : процедурный код (будь то на языке, который носит процедурный характер или просто написан в этом стиле), предлагает небольшую помощь для наложения ограничений на изменение состояния. Все может измениться в любое время из любого места. Вызов функций / методов может иметь пугающее действие на расстоянии. Автоматизированное тестирование является более сложным, поскольку успешность тестов определяется значением нелокальных переменных, которые широко доступны / доступны.

Две другие большие парадигмы программирования (ОО и функциональные) предлагают интересные, но почти диаметрально противоположные решения проблемы сложности, связанной с состоянием. В функциональном программировании стараются избегать этого полностью: функции, как правило, чистые, операции над структурами данных возвращают копии, а не обновляют оригинал на месте и т. Д.

С другой стороны, ОО предлагает инструменты для управления состоянием (вместо инструментов, позволяющих избежать его). В дополнение к инструментам языкового уровня, таким как модификаторы доступа (защищенные / публичные / приватные), геттеры и сеттеры и т. Д., Существует также ряд связанных соглашений, таких как Закон Деметры, который рекомендует не использовать объекты для получения данных других объектов. ,

Обратите внимание, что вам не нужны объекты, чтобы действительно что-то из этого делать: у вас может быть замыкание, содержащее недоступные данные и возвращающее структуру данных функций для манипулирования им. Но разве это не объект? Разве это не соответствует нашему представлению о том, что такое объект, интуитивно? И если у нас есть эта концепция, не лучше ли переформулировать ее на языке, а не (как уже говорили другие ответы) полагаться на комбинаторный взрыв конкурирующих специальных реализаций?


5

Нужны ли нам ОО-языки для управления сложностью программного обеспечения?

Нет. Но они могут помочь во многих ситуациях.

В течение десятилетий я использовал в основном один ОО-язык, но большая часть моего кода на самом деле строго процедурная. Однако для всего, что связано с GUI, я использую обширную OO-библиотеку языка встроенных методов и объектов, потому что это чрезвычайно упрощает мой код.

Например, приложение Windows, использующее исходный низкоуровневый API-интерфейс Windows для отображения формы, кнопки и поля редактирования, требует большого количества кода, в то время как использование библиотек объектов, поставляемых с Visual Basic, C # или Delphi, делает то же самое. Программа крошечная и тривиальная. Итак, мой OO-код обычно относительно мал и для GUI, в то время как мой код, который вызывают эти объекты, обычно намного больше и обычно не связан с OO (хотя он может варьироваться в зависимости от проблемы, которую я пытаюсь решить).

Я видел ОО-программы, которые были слишком сложными, основывались на сложных эзотерических правилах о том, как объекты были реализованы, и могли бы быть намного проще, если бы были написаны без ОО-концепций. Я также видел обратное: сложные системы вопиют о необходимости повторной реализации и упрощения с помощью объектов.

По мере накопления опыта вы обнаружите, что в разных ситуациях требуются разные инструменты и решения, и один размер подходит не всем.


3

Как человек, который участвует в очень большом проекте, полностью написанном на C, я могу с уверенностью сказать, что ответ - «нет».

Модульность важна. Но модульность может быть реализована практически на любом приличном языке. Например, C поддерживает модульную компиляцию, файлы заголовков и типы структур. Этого достаточно для 99% случаев. Определите модуль для каждого нового необходимого вам абстрактного типа данных и определите функции для работы с этим типом данных. Иногда вам нужна производительность, и эти функции находятся в заголовочном файле как встроенные функции, в других случаях вы будете использовать стандартные функции. Это все невидимо для пользователя, какой путь выбран.

Состав несущих конструкций. Например, у вас может быть заблокированная хеш-таблица, состоящая из блокировки мьютекса и обычной хеш-таблицы. Это не объектно-ориентированное программирование; подклассы не делаются. Композиция - это инструмент, который намного старше идеи объектно-ориентированного программирования.

Для 1% случаев, когда модульности на уровне компиляции недостаточно, и вам нужна модульность во время выполнения, есть вещь, называемая указателями на функции. Они позволяют иметь индивидуальные реализации четко определенного интерфейса. Обратите внимание, что это не объектно-ориентированное программирование на не объектно-ориентированном языке. Это определение интерфейса, а затем его реализация. Например, подклассы здесь не используются.

Рассмотрим, пожалуй, самый сложный проект с открытым исходным кодом. А именно, ядро ​​Linux. Он полностью написан на языке Си. Это делается главным образом с помощью стандартных инструментов модульности уровня компиляции, включая композицию, а затем иногда, когда требуется модульность во время выполнения, используются функциональные указатели для определения и реализации интерфейса.

Если вы попытаетесь найти пример объектно-ориентированного программирования в ядре Linux, я уверен, что найти такой пример будет очень сложно, если только вы не расширили объектно-ориентированное программирование, включив в него такие стандартные задачи, как «определение интерфейса и его реализация».

Обратите внимание, что даже язык программирования C поддерживает объектно-ориентированное программирование, если оно вам действительно нужно. Например, рассмотрим графический интерфейс пользователя GTK. Это на самом деле объектно-ориентированный, хотя написано на не объектно-ориентированном языке. Итак, это показывает, что идея о том, что вам нужен «объектно-ориентированный язык», глубоко ошибочна. Объектно-ориентированный язык не может ничего сделать, чего не может сделать другой тип языка. Более того, если вы опытный программист, вы очень легко умеете писать объектно-ориентированный код на любом языке. Например, использование C не является бременем.

Итак, выводы заключаются в том, что объектно-ориентированные языки, вероятно, полезны только для начинающих программистов, которые не понимают, как на самом деле реализована концепция. Однако я не хотел бы быть рядом с любым проектом, где программисты - такие начинающие программисты.


1
«[...] выводы заключаются в том, что объектно-ориентированные языки, вероятно, полезны только для начинающих программистов, которые не понимают, как на самом деле реализована концепция». Интересно. Какие языки ты имеешь в виду? У вас есть примеры проектов с открытым исходным кодом, написанных на этих языках, которые потерпели неудачу или не потерпели неудачу?
Винсент

3
Вы поднимаете некоторые хорошие моменты, но ваша главная идея ошибочна. Да, можно реализовать такие концепции ОО, как инкапсуляция, виртуальная диспетчеризация, наследование и даже сборка мусора, на языке, подобном C. Это также возможно сделать в сборке. Это не облегчает программирование. Программирование и особенно проектирование на языке, подобном C, определенно сложнее, чем на языке OO. В C вам нужно сопоставить концепции с их реализацией, на языке OO вам не нужно делать этот шаг (по крайней мере, не для концепций OO).
fishinear

1
«[указатели на функции] позволяют иметь отдельные реализации четко определенного интерфейса. Обратите внимание, что это не объектно-ориентированное программирование на необъектно-ориентированном языке. Это определение интерфейса, а затем его реализация». Извините, но это совершенно неправильно, потому что это именно то , что ООП. «Например, подклассификация здесь не используется» Подклассификация не является обязательной функцией ООП. Обратите внимание, например, что JavaScript является объектно-ориентированным языком, который не имеет подклассов (или, в этом отношении, классов вообще ... Только объекты, которые содержат ссылки на функции).
Жюль

1
Чтобы прояснить мой последний комментарий, я хочу сказать, что основной отличительный фактор между ООП (не обязательно каким-либо конкретным языком ОО) и другими методами заключается в том, что в ООП мы определяем интерфейсы, которые абстрактно работают с данными без необходимости знать формат этих данных с помощью привязка реализации интерфейсов к самим данным. Вот что такое ООП. Метод реализации не имеет значения, будь то класс стиля Java, объект JavaScript (по сути, карта имени к атрибуту, которая может быть либо данными, либо кодом), либо структура, содержащая указатели на функции и void * для данных.
Жюль

1
«Итак, выводы заключаются в том, что объектно-ориентированные языки, вероятно, полезны только для начинающих программистов, которые не понимают, как на самом деле реализуется концепция».… И это, честно говоря, просто оскорбительно. Я достаточно хорошо знаю, как реализуются эти концепции. Я проделал достаточно работы, чтобы потом быть опытным. В прошлом я даже реализовывал интерпретатор и компилятор для ОО-языков. Но поскольку я предпочитаю работать на языках более высокого уровня, которые имеют объекты первого класса, я должен быть начинающим программистом, с которым вы бы не хотели работать ?!
Жюль

2

Причиной введения парадигм программирования, включая объектно-ориентированные методы, является упрощение создания более сложных и мощных программ. В августовском выпуске журнала Byte Magazine за 1981 год Даниэль Ингаллс , один из ключевых создателей Smalltalk, определил «объектно-ориентированный» как включающий следующие возможности:

  • автоматическое управление хранением
  • возможность обмена сообщениями
  • единая метафора, которая применяется ко всем операциям языка
  • ни один компонент не зависит от внутренних компонентов другого компонента (модульность)
  • программа определяет только поведение объектов, а не их представление (полиморфизм)
  • каждый компонент должен появляться только в одном месте (факторинг)
  • использование виртуальной машины, которая не зависит от оборудования
  • каждый доступный для пользователя компонент должен быть доступен для наблюдения и контроля (принцип реагирования)
  • не должно быть общего контроллера (без операционной системы)

Это были принципы, которые Ingalls определили в качестве основных принципов проектирования SmallTalk-80, разработанного Xerox Parc Research. В вышеупомянутой журнальной статье вы можете прочитать подробное описание каждого из этих принципов и их вклад в объектно-ориентированную парадигму по Инголлу.

Все эти принципы могут применяться с использованием любого полного языка Тьюринга, будь то процедурный, ассемблер или любой другой. Это принципы проектирования, а не спецификация языка. Объектно-ориентированный язык призван облегчить использование этих принципов при создании программного обеспечения.

Например, если взять первый из принципов Ingall (автоматическое управление хранилищем), любой может написать свою собственную систему автоматического управления хранилищем на процедурном языке, но для этого потребуется много работы. При использовании такого языка, как SmallTalk или Java, в котором встроено автоматическое управление хранением, программисту не нужно выполнять столько работы по управлению памятью. Компромисс в том, что программист получает меньше контроля над тем, как используется память. Итак, есть выгода и недостаток. Идея парадигмы проектирования, подобной объектно-ориентированному программированию, заключается в том, что преимущества этой парадигмы перевесят недостатки по крайней мере для некоторых программистов.


Я думаю, что те же правила будут применяться в случае домен-специфических языков. Те же преимущества и недостатки ... Единственное отличие состоит в том, что DSL могут быть сделаны достаточно простыми для конечных пользователей, чтобы работать с ними, потому что «язык» соответствует их пониманию проблемного пространства, и больше ничего не включено.

0

Один из способов управления сложностью программного обеспечения состоит в том, чтобы полностью отделить структуру от желаемых действий, используя язык, специфичный для предметной области . Это означает, что уровень программного кода отличается от уровня, на котором настроены желаемые результаты - совершенно другой язык или система. Когда это сделано правильно, обычный код по существу становится библиотекой, и пользователь или другой человек, создающий желаемые результаты, соединяет вещи вместе с языком сценариев или средством визуального дизайна, таким как генератор отчетов.

Для работы это требует проведения строгой границы вокруг того, какие операции будут возможны и как они связаны (язык сценариев или визуальный дизайн, например инструмент построения форм). Метаданные являются важным способом абстрагирования конфигурации времени выполнения от деталей кодирования, позволяя системе поддерживать широкий диапазон желаемых результатов. Если границы установлены и удерживаются (не принимая каждый запрос на расширение, которое приходит), у вас может быть долговечная и надежная система, которая работает для людей, без необходимости быть программистами для достижения того, чего они хотят.

Мартин Фаулер написал книгу об этом, и техника почти так же стара, как само программирование. Вы можете почти сказать, что все языки программирования являются предметно-ориентированными языками, и поэтому идея является эндемичной, упускается из виду, потому что она настолько очевидна. Но вы все равно можете создавать свои собственные сценарии или инструменты визуального дизайна, чтобы сделать вашу жизнь проще. Иногда обобщение проблемы облегчает ее решение!


0

Это очень хороший вопрос, и я чувствую, что ответы, приведенные здесь, не оправдали себя, поэтому я добавлю свои мысли.

Цель - управлять сложностью программного обеспечения . Цель не в том, чтобы «использовать ОО-язык».

Нет никакой причины для введения новой парадигмы. Это произошло естественным образом, когда кодирование стало более зрелым. Имеет смысл написать код, в котором мы добавляем вагон в конце поезда (поезд моделируется с использованием связанного списка), а не добавляем новый узел в конец связанного списка.


Кодирование в терминах реальных объектов просто очевидный и правильный способ кодирования , когда мы являемся кодированиями о реальных объектах.


Компьютер может работать с добавлением узла в конец связанного списка так же легко, как и с добавлением дополнительного тренера в конец поезда. Но людям легче работать с поездом и тренером, чем со связанным списком и узлами, даже если мы углубляемся в уровень, мы обнаруживаем, что поезд моделируется с помощью связанного списка.

Защита или шифрование файлов не может обеспечить инкапсуляцию. Противоположностью шифрования является дешифрование. Противоположностью инкапсуляции является Decapsulation, что означает декомпозицию структур и классов в языках программирования для достижения лучшей производительности. Производительность достигается за счет сокращения трафика в памяти и исключения проверок правил ООП.

Следовательно, вы можете написать код, который является как зашифрованным, так и хорошо инкапсулированным, потому что эти два понятия разные.

Инкапсуляция помогает в управлении сложностью, поскольку она близка к реальности.

Поэтому программируйте в объектах, потому что вам легче кодировать, и быстрее вам и всем остальным понять.


0

Единственное, что следует помнить, это:
ООП не о языковых особенностях; речь идет о том, как вы структурируете свой код .

ООП - это способ мышления и проектирования архитектуры вашего кода, и это можно сделать практически на любом языке. Особенно это касается низкоуровневых неOO-языков, которые называются ассемблером и C. Вы можете выполнять идеально объектно-ориентированное программирование на ассемблере, а ядро ​​Linux, написанное на C, во многих отношениях является объектно-ориентированным. ,

Тем не менее, функции OO в языке значительно сокращают объем стандартного кода, который необходимо написать для достижения желаемых результатов . Там, где вам нужно явно определить таблицу виртуальных функций и заполнить ее соответствующими указателями на функции в C, вы просто ничего не делаете в Java, и все готово. ОО-языки просто удаляют все то, что позволяет использовать Cruft, из исходного кода, скрывая его за красивыми абстракциями на уровне языка (такими как классы, методы, члены, базовые классы, неявные вызовы конструктора / деструктора и т. Д.).

Так что нет, нам не нужны ОО-языки для ООП. Просто ООП намного проще сделать с приличным языком ООП .


-1

Объектно-ориентированное программирование - это больше, чем просто модули + инкапсуляция. Как вы говорите, можно использовать модули + инкапсуляция на не объектно-ориентированном (процедурном) языке. ООП включает в себя не только это: оно включает объекты и методы. Так что нет, это не захватывает ООП. См., Например, https://en.wikipedia.org/wiki/Object-oriented_programming или хорошее введение в учебник по ООП.


Спасибо за твой ответ. Не могли бы вы порекомендовать один?
steakexchange

-2

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

Давайте представим систему из 100 классов, в каждом из которых может быть выполнено около 20 операций; это 2000 функций. Однако из них, может быть, только 500 являются полными операциями, такими как «Сохранить» и «Удалить», в то время как 1500 являются внутренними функциями, которые выполняют небольшую часть обслуживания или выполняют какую-то служебную роль. Рассмотреть возможность;

// intentionally in a non-specific language!

setName(person, name) {
    nameParts = splitPersonName(name);
    person.firstName = nameParts[0];
    person.lastName = nameParts[1];
    person.modified = true;
}

splitPersonName(name) {
    var result = [];
    result.add(name.substring(0, name.indexOf(" ")));
    result.add(name.substring(name.indexOf(" ") + 1));
    return result;
}

Поэтому SetNameфункция люди должны делать для человека, но SplitPersonNameэто функция полезности используется на человеке.

Прямое процедурное программирование не делает различий между этими двумя операциями. Это означает, что ваш 2000 функционал все соперничают за ваше внимание. Однако, если бы мы могли пометить эти функции как «доступные каждому, у кого есть запись о человеке» и «используемые только как служебная функция внутри записи о человеке», то наше внимание теперь состоит в том, что 500 «доступны для всех» функций и 15 «полезность» функции для класса, который вы редактируете.

Вот что publicи privateделай;

public class Person {
    public void setName(...) {...}
    private string[] splitPersonName(...) { ...}
}

1
Я не уверен, правильно ли вы поняли мой вопрос. Я уже осознаю, что инкапсуляция и сокрытие данных - это способ управления сложностью. Я просто думаю, что это можно легко сделать и на процедурных языках, разделив программу на модули, которые выполняют четко определенные простые задачи, внутренняя работа которых указана в отдельных защищенных источниках. Так зачем ООП, когда мы можем делать это на процедурных языках? Это мой вопрос.
steakexchange

2
Я предполагаю, что мой ответ таков: если вы хотите сделать что-то подобное, вам нужно будет написать для этого специальные инструменты и языковые конструкции (например, специальный вызов include для включения файла, который может не быть включены в другом месте). Начав этот путь, вы фактически начали реализовывать объектно-ориентированный язык по-своему. Например, C ++ изначально был препроцессором, который создавал обычный C , и я подозреваю, что когда вы внедряете свою систему, она выглядит очень похоже на C ++ поверх C.
user62575

3
@steakexchange Обратите внимание, что ООП был разработан во времена, когда многие процедурные языки не имели подобных модулей. Некоторые даже не назвали бы такие языки процедурными. На самом деле, нет ничего, что говорит, что процедурный язык не должен быть ОО или наоборот. Будьте осторожны с этикетками - они могут легко ввести вас в заблуждение. Если ваш процедурный язык поддерживает модули с открытыми и закрытыми полями и процедурами, что хорошо для вас :) Основное различие между «традиционным процедурным» и «ООП» заключается в том, что диспетчеризация вызовов более гибкая в ООП - действительно, в строгом ООП вы никогда не знаешь, какой код ты называешь.
Луаан

2
@steakexchange В языках семейства ML модули работают отлично, и в сочетании с лямбдами они дают вам всю мощь любого языка OO (в конце концов, функция - это интерфейс с одним методом - разве это не то, что рекомендуется "хороший код", ребята в ОО?: P). По разным причинам они все еще используются реже, чем более процедурные языки, такие как C ++ или Java, но они действительно имеют свою привлекательность, и многие люди пытаются обучить людей тому, как они могут упростить свою жизнь (с большим или меньшим успехом).
Луаан

С эффективно имеет эти вещи. Он имеет модули (файлы .c) с интерфейсами (файлы .h) и может иметь публичные (extern) и непубличные (extern) методы (функции). Вы даже можете иметь полиморфизм бедняков с массивами указателей на функции, я не говорю, что OO легко в C (или, может быть, в здравом уме), но инкапсуляция довольно проста,
Ник
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.