Это будет очень нетехнический, мягкий вопрос, и я не уверен, что это правильная платформа. Но я начинающий студент CS, поэтому надеюсь, что вы, ребята, это терпите.
В первом семестре мы познакомились с такими понятиями ООП, как инкапсуляция, сокрытие данных, модульность, наследование и т. Д. Через Java и UML. (Java - мой первый язык программирования)
Насколько я понимаю, ООП - это способ управления сложностью программного обеспечения. Но его принципы не новы и не уникальны, они в некотором смысле универсальны для всех областей техники.
Например, автомобиль - это очень сложная структура, сложностью которой управляет иерархия модульных и инкапсулированных компонентов с четко определенным поведением и интерфейсами.
Но я не понимаю причину введения новой парадигмы программирования. Я думаю, что все принципы, используемые для управления сложностью, могут быть реализованы с помощью процедурных языков программирования. Например, для модульности мы можем просто разделить программу на множество небольших программ, которые выполняют четко определенные задачи, код которых содержится в отдельных файлах. Эти программы будут взаимодействовать друг с другом через их четко определенный ввод и вывод. Файлы могут быть защищены (зашифрованы?) Для достижения инкапсуляции. Для повторного использования кода мы можем просто вызывать эти файлы всякий раз, когда они нужны в новых программах. Разве это не отражает все, что такое ООП, или я упускаю что-то очень очевидное?
Я не прошу доказательств того, что ООП управляет сложностью. На мой взгляд, это действительно так. Но я думаю, что все принципы, используемые для управления сложностью, такие как модульность, инкапсуляция, скрытие данных и т. Д., Могут быть легко реализованы процедурными языками. Так зачем же ООП, если мы можем управлять сложностью без нее?
источник
Ответы:
Позвольте мне попробовать с очень низким теоретическим ответом :)
Что вы действительно спрашиваете: зачем включать поддержку Object Orientation (OO) непосредственно в язык, когда процедурные языки могут использоваться для разработки и написания OO-кода?
И ответ таков: иметь стандарт того, как ОО выражается в исходном коде, чтобы у вас не было 22 разных реализаций для одной и той же абстракции.
Например, допустим, я создал а
MagicButton
и а,MagicSlider
которые можно использовать в системе пользовательского интерфейса. Мне нужен способ сгруппировать методы, которые можно использовать с MagicButton, методы, которые можно использовать только с MagicSlider, и методы, которые могут использоваться обоими. Эти объекты имеют несколько общих методов, потому что они оба являются объектами Magic gui.Я могу выполнить группировку, назвав функции особым образом
MagicSlider_DoSomething ...
, включив методы в определенные файлы, названные особым образомMagicSliderMethods.XXX
, или я мог бы найти какой-то другой особый способ сделать то же самое. Если в языке не существует стандартного способа сделать это, я сделаю это не так, как вы, и не так, как кто-либо другой. Это делает совместное использование кода намного сложнее.Да, поздняя диспетчеризация - виртуальные методы на ОО-языках - может быть реализована на процедурных языках, но существует много разных способов ее реализации. В зависимости от того, кто написал код, вы получите разные реализации ОО внутри одной и той же программы.
Подумайте о плохом разработчике обслуживания. Этот человек должен управлять различными абстракциями объектов и разными способами вызывать виртуальные методы в зависимости от того, кто написал исходный код.
Также: Наличие абстракций в языке позволяет продвинутым редакторам кода, таким как Eclipse, выполнять большой статический анализ кода. Например, Eclipse может предложить список всех методов, которые могут использоваться на объекте, а также автоматическую реализацию пустых «методов TODO». Eclispe точно знает, какие методы должен реализовывать ваш класс, основываясь на том, какие классы вы расширяете и какие интерфейсы вы реализуете. Это было бы почти невозможно, если бы не было языкового стандарта для ОО.
источник
Ни одна из этих концепций ООП. Все они существуют вне ОО, независимо от ОО, и многие даже были изобретены до ОО.
Итак, если вы думаете , что что то , что OO это все о, то ваш вывод прав: вы можете сделать все из тех , на процедурных языках, потому что они не имеют ничего общего с ОО .
Например, одна из основополагающих статей о модульности - «Критерии для использования при разложении систем на модули» . Там нет упоминания о OO там. (Он был написан в 1972 году, к тому времени ОО все еще оставалась неясной нишей, хотя ему уже более десяти лет.)
Хотя абстракция данных важна в ОО, она является скорее следствием основной функции ОО (обмена сообщениями), чем определяющей. Кроме того, очень важно помнить, что существуют различные виды абстракции данных. Два наиболее распространенных вида абстракции данных, используемых сегодня (если мы игнорируем «никакой абстракции вообще», которая, вероятно, все еще используется больше, чем два других вместе взятых), это Абстрактные типы данных и объекты . Итак, просто говоря «сокрытие информации», «инкапсуляция» и «абстракция данных», вы ничего не сказали об ОО, поскольку ОО - это всего лишь одна из форм абстракции данных, и эти два на самом деле принципиально различны:
Кстати, это означает, что в Java классы не являются объектно-ориентированными. Два экземпляра одного класса могут получить доступ к представлению друг друга и частной реализации. Поэтому экземпляры классов не являются объектами, а фактически являются экземплярами ADT. Java
interface
s, однако, действительно обеспечивают объектно-ориентированной абстракции данных. Итак, другими словами: только экземпляры интерфейсов являются объектами в Java, экземпляры классов - нет.В основном, для типов вы можете использовать только интерфейсы. Это означает, что типы параметров методов и конструкторов, типы возвращаемых методов, типы полей экземпляров, статические поля и локальные поля, аргумент
instanceof
оператора или оператора приведения и аргументы типа для конструктора универсального типа всегда должны быть интерфейсами. Класс может использоваться только сразу послеnew
оператора, нигде больше.То, что вы описываете, является OO.
Это действительно хороший способ думать о ОО. Фактически, это именно то, что имели в виду первоначальные изобретатели ОО. (Алан Кей пошел еще дальше: он предполагал, что множество маленьких компьютеров посылают сообщения друг другу по сети.) То, что вы называете «программой», обычно называется «объектом», и вместо «звонка» мы обычно говорим «отправить сообщение». ».
Ориентация на объект - это все об обмене сообщениями (он же динамическая диспетчеризация ). Термин «Объектно-ориентированный» был придуман доктором Аланом Кей, главным разработчиком Smalltalk, и он определяет его так :
Давайте разберемся с этим:
С точки зрения реализации обмен сообщениями - это вызов процедур с поздней привязкой, и если вызовы процедур связаны с поздней привязкой, вы не можете знать во время разработки, что вы собираетесь вызывать, поэтому вы не можете делать какие-либо предположения о конкретном представлении состояния. Итак, на самом деле речь идет об обмене сообщениями, позднее связывание является реализацией обмена сообщениями, а инкапсуляция является следствием этого.
Позже он пояснил, что « большая идея - это« обмен сообщениями » », и сожалеет, назвав его «объектно-ориентированным» вместо «ориентированного на сообщения», потому что термин «объектно-ориентированный» акцентирует внимание на неважной вещи (объектах). ) и отвлекает от того, что действительно важно (обмен сообщениями):
(Конечно, сегодня большинство людей даже не сосредотачиваются на предметах, а на классах, что еще более неправильно).
Обмен сообщениями является фундаментальным для ОО, как метафора и как механизм.
Если вы отправляете кому-то сообщение, вы не знаете, что они с ним делают. Только вещь , которую вы можете наблюдать, их ответ. Вы не знаете, обрабатывали ли они сообщение сами (т. Е. Если у объекта есть метод), пересылали ли они сообщение кому-либо еще (делегирование / передача), даже если они его понимали. Вот что такое инкапсуляция, вот что такое OO. Вы даже не можете отличить прокси-сервер от реального, если он отвечает так, как вы ожидаете.
Более «современным» термином для «обмена сообщениями» является «динамическая диспетчеризация метода» или «вызов виртуального метода», но он теряет метафору и фокусируется на механизме.
Итак, есть два способа взглянуть на определение Алана Кея: если вы посмотрите на него, стоящее само по себе, вы можете заметить, что обмен сообщениями - это в основном вызов процедуры с поздней привязкой, а поздняя привязка подразумевает инкапсуляцию, поэтому мы можем заключить, что # 1 и # 2 на самом деле являются избыточными, а OO - все о позднем связывании.
Однако позже он пояснил, что важной вещью является обмен сообщениями, и поэтому мы можем взглянуть на него под другим углом зрения: обмен сообщениями связан с запозданием. Теперь, если бы обмен сообщениями был единственно возможным, тогда №3 был бы тривиально верным: если есть только одна вещь, и эта вещь связана с опозданием, то все вещи связаны с опозданием. И снова, инкапсуляция следует из обмена сообщениями.
Подобные замечания также делаются в « Об понимании абстракции данных», вновь рассмотренном Уильямом Кук, а также в его предложении по упрощенным, современным определениям «Объект» и «Объектно-ориентированный» :
В Smalltalk-72 даже не было никаких объектов! Были только потоки сообщений, которые были проанализированы, переписаны и перенаправлены. Сначала появились методы (стандартные способы анализа и перенаправления потоков сообщений), затем появились объекты (группы методов, которые разделяют некоторые частные состояния). Наследование появилось намного позже, и классы были введены только как способ поддержки наследования. Если бы исследовательская группа Кея уже знала о прототипах, они, вероятно, никогда бы не представили классы.
Бенджамин Пирс в « Типах и языках программирования» утверждает, что определяющей чертой объектно-ориентации является открытая рекурсия .
Итак, по словам Алана Кея, OO - это все о сообщениях. По словам Уильяма Кука, ОО - это динамическая диспетчеризация методов (что на самом деле одно и то же). По словам Бенджамина Пирса, OO - это все об открытой рекурсии, что в основном означает, что самореференции динамически разрешаются (или, по крайней мере, так думают), или, другими словами, обмениваются сообщениями.
Как видите, человек, который придумал термин «ОО», имеет довольно метафизический взгляд на объекты, Кук - довольно прагматичный взгляд, а Пирс - очень строгий математический взгляд. Но важно то, что философ, прагматик и теоретик все согласны! Обмен сообщениями является одним из столпов ОО. Период.
Обратите внимание, что здесь нет упоминания о наследовании! Наследование не обязательно для ОО. В общем, большинство ОО-языков имеют некоторый способ повторного использования реализации, но это не обязательно должно быть наследованием. Это также может быть, например, некоторая форма делегирования. Фактически, в Орландском договоре делегирование рассматривается как альтернатива наследования, и как различные формы делегирования и наследования приводят к различным точкам проектирования в пространстве проектирования объектно-ориентированных языков. (Обратите внимание, что на самом деле даже в языках, которые поддерживают наследование, таких как Java, людей фактически учат избегать его, снова указывая на то, что оно не нужно для ОО.)
источник
Когда вы говорите «очень легко», вы делаете очень смелое заявление. Я читаю это так: «Я не вижу трудности, поэтому она не должна быть очень большой». Если сформулировать это таким образом, становится ясно, что вы не спрашиваете «зачем нам нужен ОО», а спрашиваете: «Почему трудности, с которыми столкнулись другие программные парадигмы, которые приводят к изобретению ОО, сразу не очевидны для меня? "
Ответ на этот вопрос заключается в том, что многие из этих трудностей не существуют в тех программах, над которыми вы работаете. Вас не просят обновить 40-летний код спагетти. Вы не пытаетесь написать новый диспетчер отображения для операционной системы. Вы не отлаживаете многопоточные распределенные приложения.
Для многих игрушечных программ, которые мы, ученики CS, ставим перед собой задачей, мы могли бы писать их на бейсике или ассемблере так же, как на Java или Python. Это связано с тем, что сложность задач настолько низка, что существует только один разработчик, нет проблем с функциональной совместимостью, производительность не имеет значения, и код, скорее всего, будет запускаться лишь несколько раз на одной машине.
Представьте себе, что вы берете студенческого водителя и просите его в час пик выехать на оживленную улицу на механической коробке передач без синхронной сетки, направляясь к крутому склону. Катастрофа. Почему? Они не могут управлять уровнем сложности, необходимым для одновременного следования всем правилам, необходимым для этой задачи.
А теперь представьте того же студента, ту же машину, которая едет в шаговой доступности на пустой стоянке. Они в порядке, потому что их уровень мастерства соответствует задаче. Нет никакого давления, небольшого риска, и они могут взять на себя отдельные подзадачи запуска, сцепления, переключения, ускорения, рулевого управления по одному.
Этот студент может спросить, почему у нас автоматические коробки передач, если опытный водитель может делать все эти вещи одновременно? Ответ в том, что достаточно опытный водитель в оптимальных условиях не нуждается в автомате. Но мы не все профессиональные водители в отличном состоянии, и мы обычно хотим, чтобы дизайнеры автомобиля позаботились обо всей этой сложности для нас.
Опытный, достаточно дисциплинированный программист действительно может создать функционирующую систему высокой сложности на C или сборке. Но мы не все Линус Торвальдс. Мы также не должны создавать полезное программное обеспечение.
Лично я не заинтересован в том, чтобы заново изобретать все возможности современного языка, прежде чем я смогу решить проблему. Если я могу воспользоваться языком, который включает в себя решения уже решенных проблем, то почему бы и нет?
Поэтому я переверну ваш вопрос и задам вопрос: если языки предоставляют удобные функции, такие как инкапсуляция и полиморфизм, почему бы нам не использовать их?
источник
То, что вы описываете, это не ООП, а абстракция. Абстракция присутствует во всех современных моделях дизайна, даже тех, которые не являются ООП. А ООП - это очень специфический вид абстракции.
Во-первых, стоит отметить, что не существует единого определения ООП, поэтому могут быть люди, которые не согласны с тем, что я называю ООП.
Во-вторых, важно помнить, что ООП вдохновлялись традиционными моделями дизайна, поэтому сходство с дизайном автомобиля не случайно.
Тем не менее, вот несколько способов, которыми ООП имеет больше нюансов, чем вы сказали:
Инкапсуляция: речь идет не только о наличии установленного интерфейса для модуля (то есть абстракции), но и о запрете доступа за пределы этого интерфейса. В Java доступ к закрытой переменной является ошибкой компиляции, в то время как в вашей машине вы можете (в некоторых случаях) использовать вещи, которые отличаются от намеченного интерфейса.
Наследование: это действительно то, что делает ООП уникальным. После того как вы определили интерфейс, вы можете сделать несколько вещей, реализующих этот интерфейс, и вы можете сделать это иерархическим способом, изменяя определенные части их реализации, в то же время наследуя все предыдущие части, что значительно сокращает дублирование кода.
Если вы думаете с точки зрения инкапсулированных компонентов автомобиля, на самом деле нет эквивалента этому. У меня нет способа сделать механизм, выбрав другой механизм и изменив конкретную часть его реализации. (По крайней мере, я так не думаю, я не знаю много об автомобилях).
Полиморфизм . После того, как вы определили интерфейс, все, что использует этот интерфейс, должно быть неразличимо с точки зрения доступных операций, и вам не нужно знать, какая реализация используется для использования интерфейса. Именно здесь становятся важными подтипы и принцип подстановки Лискова .
Связь : ключевым аспектом ООП является то, что мы тесно связываем вещи с одинаковыми операциями и распространяем различные формы, которые они могут иметь. Данные связаны с операциями с этими данными. Это означает, что очень легко добавить новую форму данных (новую реализацию), но очень трудно добавить новую операцию в интерфейс (поскольку вам придется обновлять каждый класс, который реализует интерфейс). Это отличается от алгебраических типов данных в функциональных языках, где очень легко добавить новую операцию (вы просто пишете функцию, которая обрабатывает все случаи), но сложно добавить новый вариант (так как вам нужно добавить новый дело для всех ваших функций).
источник
Это зависит от значения слова «необходимость».
Если «нужно» значит требует, то нет, мы этого не требуем.
Если «необходимость» означает «дает сильные выгоды», то я бы сказал: «Да», мы этого желаем.
Большая фотография
ОО-языки связывают функциональность с данными.
Вы можете избежать этой привязки и написать функции, которые передают значения данных.
Но тогда вы, вероятно, столкнетесь с совокупностями данных, которые собираются вместе, и вы начнете передавать кортежи, записи или словари данных.
И действительно, вот и все вызовы методов: частичные функции на связанных наборах данных.
Функция за функцией
Особенности ООП:
Однако ни одна из этих вещей не происходит так легко, как с объектно-ориентированным языком с первоклассной поддержкой этих функций.
Рекомендации
Есть много критиков ООП .
Тем не менее, исследования показывают, что мы получаем большую производительность труда программистов от повторного использования кода через ООП. Это спорный вывод, и некоторые исследователи говорят, что они не могут воспроизвести этот прирост производительности, учитывая определенные ограничения. (источник)
Заключение
Нам не «нужен» ООП. Но в некоторых случаях пользователь хочет ООП.
Насколько я понимаю, зрелые программисты могут быть весьма продуктивными в объектно-ориентированном стиле. А когда пакеты имеют базовые объекты с простыми и понятными интерфейсами, даже новые программисты могут быстро стать достаточно продуктивными.
источник
Я постараюсь быть краток.
Основным принципом ОО является сочетание данных и поведения в одной организационной единице (объекте).
Это то, что позволяет нам контролировать сложность, и когда она появилась, это была довольно инновационная концепция. Сравните это с файлами с одной стороны (чистые данные), программами, которые читают и обрабатывают эти файлы с другой стороны (чистая логика) и выводят (снова чистые данные).
Только собрав вместе этот пакет данных и логику, смоделировав какую-то сущность реального мира, вы можете начать обмениваться сообщениями, создавать дочерние классы, отделять частные данные от общедоступных данных и поведения, реализовывать полиморфное поведение и выполнять всю эту специфическую для ОО магию.
Так что да, ОО имеет большое значение. И нет, это не просто куча старых вещей с причудливым названием.
Разобрав все это на части, взглянув на элементы, а затем сказав: «О, ну, здесь ничего такого, чего я раньше не видел», - это не признание сборки, которая содержит инновации. Результат больше, чем сумма его частей.
источник
Не существует «официального» определения объектно-ориентированного программирования, и разумные люди не согласны с тем, что на самом деле определяет качество ОО. Некоторые говорят, что обмен сообщениями, некоторые говорят о подтипах, некоторые говорят о наследовании, другие говорят о связывании данных и поведения. Это не означает, что этот термин не имеет смысла, просто вы не должны слишком увлекаться спорами о том, что такое настоящий ОО.
Инкапсуляция и модульность являются более фундаментальными принципами проектирования и должны применяться во всех парадигмах программирования. Сторонники ОО не утверждают, что эти свойства могут быть достигнуты только с ОО - только то, что ОО особенно хорошо подходит для достижения этой цели. Конечно, сторонники других парадигм, таких как, скажем, функциональное программирование, утверждают то же самое для своей парадигмы. На практике многие успешные языки являются мультипарадигмальными, и ОО, функциональные и т. Д. Должны рассматриваться как инструменты, а не как «один верный путь».
Правда, потому что в итоге вы можете делать что угодно на любом языке программирования. В некоторых языках это может быть проще, чем в других, поскольку все языки имеют свои сильные и слабые стороны.
источник
Что-то, что другие ответы не упомянули: состояние.
Вы говорите об ОО как инструменте управления сложностью . В чем сложность? Это нечеткий термин. У всех нас есть это гештальтовое ощущение того, что это значит, но это сложнее понять. Мы могли бы измерить цикломатическую сложность, то есть количество путей выполнения кода, но я не знаю, о чем мы говорим, когда используем ОО для управления сложностью.
Я думаю, что мы говорим о сложности, связанной с состоянием.
В основе инкапсуляции лежат две основные идеи . Один из них, скрытие деталей реализации , довольно хорошо освещен в других ответах. Но другой скрывает свое состояние во время выполнения . Мы не копаемся с внутренними данными объектов; мы передаем сообщения (или вызываем методы, если вы предпочитаете детали реализации, а не концепцию, как указал Йорг Миттаг). Почему?
Люди уже упоминали, что это потому, что вы не можете изменить внутреннюю структуру ваших данных, не изменив код доступа к ним, и вы хотите сделать это в одном месте (метод доступа) вместо 300 мест.
Но это также потому, что это делает код трудным для рассуждения : процедурный код (будь то на языке, который носит процедурный характер или просто написан в этом стиле), предлагает небольшую помощь для наложения ограничений на изменение состояния. Все может измениться в любое время из любого места. Вызов функций / методов может иметь пугающее действие на расстоянии. Автоматизированное тестирование является более сложным, поскольку успешность тестов определяется значением нелокальных переменных, которые широко доступны / доступны.
Две другие большие парадигмы программирования (ОО и функциональные) предлагают интересные, но почти диаметрально противоположные решения проблемы сложности, связанной с состоянием. В функциональном программировании стараются избегать этого полностью: функции, как правило, чистые, операции над структурами данных возвращают копии, а не обновляют оригинал на месте и т. Д.
С другой стороны, ОО предлагает инструменты для управления состоянием (вместо инструментов, позволяющих избежать его). В дополнение к инструментам языкового уровня, таким как модификаторы доступа (защищенные / публичные / приватные), геттеры и сеттеры и т. Д., Существует также ряд связанных соглашений, таких как Закон Деметры, который рекомендует не использовать объекты для получения данных других объектов. ,
Обратите внимание, что вам не нужны объекты, чтобы действительно что-то из этого делать: у вас может быть замыкание, содержащее недоступные данные и возвращающее структуру данных функций для манипулирования им. Но разве это не объект? Разве это не соответствует нашему представлению о том, что такое объект, интуитивно? И если у нас есть эта концепция, не лучше ли переформулировать ее на языке, а не (как уже говорили другие ответы) полагаться на комбинаторный взрыв конкурирующих специальных реализаций?
источник
Нет. Но они могут помочь во многих ситуациях.
В течение десятилетий я использовал в основном один ОО-язык, но большая часть моего кода на самом деле строго процедурная. Однако для всего, что связано с GUI, я использую обширную OO-библиотеку языка встроенных методов и объектов, потому что это чрезвычайно упрощает мой код.
Например, приложение Windows, использующее исходный низкоуровневый API-интерфейс Windows для отображения формы, кнопки и поля редактирования, требует большого количества кода, в то время как использование библиотек объектов, поставляемых с Visual Basic, C # или Delphi, делает то же самое. Программа крошечная и тривиальная. Итак, мой OO-код обычно относительно мал и для GUI, в то время как мой код, который вызывают эти объекты, обычно намного больше и обычно не связан с OO (хотя он может варьироваться в зависимости от проблемы, которую я пытаюсь решить).
Я видел ОО-программы, которые были слишком сложными, основывались на сложных эзотерических правилах о том, как объекты были реализованы, и могли бы быть намного проще, если бы были написаны без ОО-концепций. Я также видел обратное: сложные системы вопиют о необходимости повторной реализации и упрощения с помощью объектов.
По мере накопления опыта вы обнаружите, что в разных ситуациях требуются разные инструменты и решения, и один размер подходит не всем.
источник
Как человек, который участвует в очень большом проекте, полностью написанном на C, я могу с уверенностью сказать, что ответ - «нет».
Модульность важна. Но модульность может быть реализована практически на любом приличном языке. Например, C поддерживает модульную компиляцию, файлы заголовков и типы структур. Этого достаточно для 99% случаев. Определите модуль для каждого нового необходимого вам абстрактного типа данных и определите функции для работы с этим типом данных. Иногда вам нужна производительность, и эти функции находятся в заголовочном файле как встроенные функции, в других случаях вы будете использовать стандартные функции. Это все невидимо для пользователя, какой путь выбран.
Состав несущих конструкций. Например, у вас может быть заблокированная хеш-таблица, состоящая из блокировки мьютекса и обычной хеш-таблицы. Это не объектно-ориентированное программирование; подклассы не делаются. Композиция - это инструмент, который намного старше идеи объектно-ориентированного программирования.
Для 1% случаев, когда модульности на уровне компиляции недостаточно, и вам нужна модульность во время выполнения, есть вещь, называемая указателями на функции. Они позволяют иметь индивидуальные реализации четко определенного интерфейса. Обратите внимание, что это не объектно-ориентированное программирование на не объектно-ориентированном языке. Это определение интерфейса, а затем его реализация. Например, подклассы здесь не используются.
Рассмотрим, пожалуй, самый сложный проект с открытым исходным кодом. А именно, ядро Linux. Он полностью написан на языке Си. Это делается главным образом с помощью стандартных инструментов модульности уровня компиляции, включая композицию, а затем иногда, когда требуется модульность во время выполнения, используются функциональные указатели для определения и реализации интерфейса.
Если вы попытаетесь найти пример объектно-ориентированного программирования в ядре Linux, я уверен, что найти такой пример будет очень сложно, если только вы не расширили объектно-ориентированное программирование, включив в него такие стандартные задачи, как «определение интерфейса и его реализация».
Обратите внимание, что даже язык программирования C поддерживает объектно-ориентированное программирование, если оно вам действительно нужно. Например, рассмотрим графический интерфейс пользователя GTK. Это на самом деле объектно-ориентированный, хотя написано на не объектно-ориентированном языке. Итак, это показывает, что идея о том, что вам нужен «объектно-ориентированный язык», глубоко ошибочна. Объектно-ориентированный язык не может ничего сделать, чего не может сделать другой тип языка. Более того, если вы опытный программист, вы очень легко умеете писать объектно-ориентированный код на любом языке. Например, использование C не является бременем.
Итак, выводы заключаются в том, что объектно-ориентированные языки, вероятно, полезны только для начинающих программистов, которые не понимают, как на самом деле реализована концепция. Однако я не хотел бы быть рядом с любым проектом, где программисты - такие начинающие программисты.
источник
Причиной введения парадигм программирования, включая объектно-ориентированные методы, является упрощение создания более сложных и мощных программ. В августовском выпуске журнала Byte Magazine за 1981 год Даниэль Ингаллс , один из ключевых создателей Smalltalk, определил «объектно-ориентированный» как включающий следующие возможности:
Это были принципы, которые Ingalls определили в качестве основных принципов проектирования SmallTalk-80, разработанного Xerox Parc Research. В вышеупомянутой журнальной статье вы можете прочитать подробное описание каждого из этих принципов и их вклад в объектно-ориентированную парадигму по Инголлу.
Все эти принципы могут применяться с использованием любого полного языка Тьюринга, будь то процедурный, ассемблер или любой другой. Это принципы проектирования, а не спецификация языка. Объектно-ориентированный язык призван облегчить использование этих принципов при создании программного обеспечения.
Например, если взять первый из принципов Ingall (автоматическое управление хранилищем), любой может написать свою собственную систему автоматического управления хранилищем на процедурном языке, но для этого потребуется много работы. При использовании такого языка, как SmallTalk или Java, в котором встроено автоматическое управление хранением, программисту не нужно выполнять столько работы по управлению памятью. Компромисс в том, что программист получает меньше контроля над тем, как используется память. Итак, есть выгода и недостаток. Идея парадигмы проектирования, подобной объектно-ориентированному программированию, заключается в том, что преимущества этой парадигмы перевесят недостатки по крайней мере для некоторых программистов.
источник
Один из способов управления сложностью программного обеспечения состоит в том, чтобы полностью отделить структуру от желаемых действий, используя язык, специфичный для предметной области . Это означает, что уровень программного кода отличается от уровня, на котором настроены желаемые результаты - совершенно другой язык или система. Когда это сделано правильно, обычный код по существу становится библиотекой, и пользователь или другой человек, создающий желаемые результаты, соединяет вещи вместе с языком сценариев или средством визуального дизайна, таким как генератор отчетов.
Для работы это требует проведения строгой границы вокруг того, какие операции будут возможны и как они связаны (язык сценариев или визуальный дизайн, например инструмент построения форм). Метаданные являются важным способом абстрагирования конфигурации времени выполнения от деталей кодирования, позволяя системе поддерживать широкий диапазон желаемых результатов. Если границы установлены и удерживаются (не принимая каждый запрос на расширение, которое приходит), у вас может быть долговечная и надежная система, которая работает для людей, без необходимости быть программистами для достижения того, чего они хотят.
Мартин Фаулер написал книгу об этом, и техника почти так же стара, как само программирование. Вы можете почти сказать, что все языки программирования являются предметно-ориентированными языками, и поэтому идея является эндемичной, упускается из виду, потому что она настолько очевидна. Но вы все равно можете создавать свои собственные сценарии или инструменты визуального дизайна, чтобы сделать вашу жизнь проще. Иногда обобщение проблемы облегчает ее решение!
источник
Это очень хороший вопрос, и я чувствую, что ответы, приведенные здесь, не оправдали себя, поэтому я добавлю свои мысли.
Цель - управлять сложностью программного обеспечения . Цель не в том, чтобы «использовать ОО-язык».
Нет никакой причины для введения новой парадигмы. Это произошло естественным образом, когда кодирование стало более зрелым. Имеет смысл написать код, в котором мы добавляем вагон в конце поезда (поезд моделируется с использованием связанного списка), а не добавляем новый узел в конец связанного списка.
Кодирование в терминах реальных объектов просто очевидный и правильный способ кодирования , когда мы являемся кодированиями о реальных объектах.
Компьютер может работать с добавлением узла в конец связанного списка так же легко, как и с добавлением дополнительного тренера в конец поезда. Но людям легче работать с поездом и тренером, чем со связанным списком и узлами, даже если мы углубляемся в уровень, мы обнаруживаем, что поезд моделируется с помощью связанного списка.
Защита или шифрование файлов не может обеспечить инкапсуляцию. Противоположностью шифрования является дешифрование. Противоположностью инкапсуляции является Decapsulation, что означает декомпозицию структур и классов в языках программирования для достижения лучшей производительности. Производительность достигается за счет сокращения трафика в памяти и исключения проверок правил ООП.
Следовательно, вы можете написать код, который является как зашифрованным, так и хорошо инкапсулированным, потому что эти два понятия разные.
Инкапсуляция помогает в управлении сложностью, поскольку она близка к реальности.
Поэтому программируйте в объектах, потому что вам легче кодировать, и быстрее вам и всем остальным понять.
источник
Единственное, что следует помнить, это:
ООП не о языковых особенностях; речь идет о том, как вы структурируете свой код .
ООП - это способ мышления и проектирования архитектуры вашего кода, и это можно сделать практически на любом языке. Особенно это касается низкоуровневых неOO-языков, которые называются ассемблером и C. Вы можете выполнять идеально объектно-ориентированное программирование на ассемблере, а ядро Linux, написанное на C, во многих отношениях является объектно-ориентированным. ,
Тем не менее, функции OO в языке значительно сокращают объем стандартного кода, который необходимо написать для достижения желаемых результатов . Там, где вам нужно явно определить таблицу виртуальных функций и заполнить ее соответствующими указателями на функции в C, вы просто ничего не делаете в Java, и все готово. ОО-языки просто удаляют все то, что позволяет использовать Cruft, из исходного кода, скрывая его за красивыми абстракциями на уровне языка (такими как классы, методы, члены, базовые классы, неявные вызовы конструктора / деструктора и т. Д.).
Так что нет, нам не нужны ОО-языки для ООП. Просто ООП намного проще сделать с приличным языком ООП .
источник
Объектно-ориентированное программирование - это больше, чем просто модули + инкапсуляция. Как вы говорите, можно использовать модули + инкапсуляция на не объектно-ориентированном (процедурном) языке. ООП включает в себя не только это: оно включает объекты и методы. Так что нет, это не захватывает ООП. См., Например, https://en.wikipedia.org/wiki/Object-oriented_programming или хорошее введение в учебник по ООП.
источник
Основная причина в том, что, поскольку программа становится все более сложной, вам необходимо сделать некоторые ее части невидимыми для других частей, или сложность приложения и количество функций сделают ваш мозг из ваших ушей.
Давайте представим систему из 100 классов, в каждом из которых может быть выполнено около 20 операций; это 2000 функций. Однако из них, может быть, только 500 являются полными операциями, такими как «Сохранить» и «Удалить», в то время как 1500 являются внутренними функциями, которые выполняют небольшую часть обслуживания или выполняют какую-то служебную роль. Рассмотреть возможность;
Поэтому
SetName
функция люди должны делать для человека, ноSplitPersonName
это функция полезности используется на человеке.Прямое процедурное программирование не делает различий между этими двумя операциями. Это означает, что ваш 2000 функционал все соперничают за ваше внимание. Однако, если бы мы могли пометить эти функции как «доступные каждому, у кого есть запись о человеке» и «используемые только как служебная функция внутри записи о человеке», то наше внимание теперь состоит в том, что 500 «доступны для всех» функций и 15 «полезность» функции для класса, который вы редактируете.
Вот что
public
иprivate
делай;источник