Преимущества объектно-ориентированного программирования [закрыто]


35

Примечание : этот вопрос является отредактированной выдержкой из блога, который я написал несколько месяцев назад. После размещения ссылки на блог в комментарии к Programmers.SE кто-то попросил меня разместить здесь вопрос, чтобы они могли на него ответить. Это сообщение мой самый популярный, так как люди , кажется, типа «я не получаю объектно-ориентированное программирование» в Google много . Не стесняйтесь ответить здесь или в комментарии на Wordpress.

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

Может кто-нибудь дать мне свои идеи о преимуществах объектно-ориентированного программирования?


2
Ох, хороший - сложно придумать определение, с которым согласятся все, кто говорит, что они делают ООП! (Даже пренебрегая теми, кто на самом деле просто занимается, например, процедурным программированием в ООП одежде.)
SamB,

10
Это действительно звучит как "Я не понимаю программирование на C. Разве мы не можем просто использовать язык ассемблера?" мне.
ТИА

2
@Joel: я не обязательно знаю тех же неинформированных сторонников, что и вы, но я думаю, что хорошей частью этого может быть то, что они были введены в программирование классами на ОО-языках. Если это ваш базовый уровень, вы не понимаете, как это на шаг вперед. Моим первым языком был Applesoft BASIC, и я выучил несколько диалектов BASIC, а также C, Pascal и немного ассемблера x86, прежде чем Delphi и C ++ познакомили меня с ООП. Люди, которые почувствовали разницу, могут лучше объяснить это.
Мейсон Уилер

3
Более негативные комментарии по поводу ООП здесь: вредные.кат-v.org/software/OO_programming , в том числе цитаты из Дейкстры и Роба Пайка.
imgx64

3
@Joel: Вы ударили мое возражение против ООП по голове. Люди, которые являются ООП-единомышленниками, обычно имеют солидный взгляд на процедурное программирование и практически не имеют опыта в любой другой парадигме. Функциональное программирование им показалось бы совершенно чуждым (доказательство: посчитайте, сколько людей в последнее время спрашивают, как делать классы и объекты в Erlang по какой-то причудливой причине), и логическое программирование взорвало бы их головы, я убежден. Я могу только вообразить, что некоторые из действительно странных парадигм сделали бы с ними ....
ПРОСТО МОЕ правильное МНЕНИЕ

Ответы:


7

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

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

Вот на что похоже процедурное программирование.

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

Что касается преимуществ объектной ориентации перед не объектно-ориентированным программным обеспечением:

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

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

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

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

46

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

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

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

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

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

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

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

РЕДАКТИРОВАТЬ: В ответ на вопрос Джоэля в комментариях,

Можете ли вы объяснить, что содержит «объектно-ориентированная программа» (кроме этих причудливых определений, которые вы наметили), которая принципиально отличается от императивной программы? Как ты "получаешь мяч?"

Небольшой отказ от ответственности здесь. Моя модель «объектно-ориентированной программы» - это в основном модель Delphi, которая очень похожа на модель C # / .NET, так как они были созданы бывшими членами команды Delphi. То, что я здесь говорю, может не применяться или не применяться так же на других ОО-языках.

Объектно-ориентированная программа - это программа, в которой вся логика структурирована вокруг объектов. Конечно, это должно быть где-то загружено. Ваша типичная Delphi-программа содержит код инициализации, который создает одноэлементный объект с именем Application. В начале программы она вызывает Application.Initialize, затем вызывает Application.CreateFormдля каждой формы, которую вы хотите загрузить в память с самого начала, а затем Application.Run,которая отображает основную форму на экране и запускает цикл ввода-вывода, который формирует ядро ​​любого интерактивные компьютерные программы.

Приложение и ваши формы опрашивают входящие события из ОС и переводят их в вызовы методов вашего объекта. Одна вещь, которая очень распространена, - это использование обработчиков событий или «делегатов» в .NET-говорящих. У объекта есть метод, который говорит: «делайте X и Y, но также проверяйте, назначен ли этот конкретный обработчик события, и вызывайте его, если он есть». Обработчик событий - это указатель на метод - очень простое замыкание, которое содержит ссылку на метод и ссылку на экземпляр объекта - которое используется для расширения поведения объектов. Например, если у меня есть объект кнопки в моей форме, я настраиваю его поведение, подключая обработчик события OnClick, который заставляет некоторый другой объект выполнять метод при нажатии кнопки.

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


4
Я думаю, что вы действительно ударили ногтем по голове с этим ответом. Когда вы инкапсулируете манипулирование данными (ОК, они выделяют указатель здесь, а затем смещают туда несколько битов ...), все, что остается, - это логика высокого уровня программы (если все сделано правильно, вы можете написать ужасный код в любой парадигме .) .
ChaosPandion

2
Это отличное объяснение, спасибо. Можете ли вы объяснить, что содержит «объектно-ориентированная программа» (кроме этих причудливых определений, которые вы наметили), которая принципиально отличается от императивной программы? Как ты "получаешь мяч?"
Джоэл Дж. Адамсон

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

1
@Karthik Немного опоздал на вечеринку, но на самом деле нет, ООП не обязательно означает повторное использование классов. Вся концепция системы типов - это абстракция для группировки объектов в общих интерфейсах. Но вы также можете использовать систему на основе прототипов (например, Javascript), где вызовы метода для объекта разрешают цепочку прототипов, а не цепочку классов. Он по-прежнему обладает всеми функциями ООП, но допускает специальные объекты и типы, просто добавляя новые вещи в существующий объект. Затем вы можете клонировать этот объект, чтобы получить больше этого нового типа.
CodexArcanum

2
+1 за точное указание истинного преимущества ООП. «По своей сути ООП - это способ использовать императивную парадигму для лучшего управления высокой степенью сложности путем создания« умных »структур данных, которые моделируют проблемную область».
Картик Сринивасан,

6

Я думаю, что ООП - это просто имя, данное тому, что вы, возможно, испытали на этом пути, как и я.

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

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

Я не уверен, что они когда-либо встроили это в Фортран, но это легко сделать в Си и его потомках.

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


5

Существуют различные виды ОО-систем, и трудно получить определение, с которым все согласятся. Вместо того, чтобы пытаться показать, как ОО Java похож на Common Lisp Object System, я начну с чего-то более обычного, шаг за шагом.

Предположим, у вас есть много объектов, существующих как разбросанные данные. Точки, например, могут быть элементами в массиве X, Y и Z. Для того , чтобы рассмотреть саму точку, это имеет смысл , чтобы вытащить все данные вместе в нечто вроде C struct.

Теперь для любого объекта данных у нас есть все данные вместе. Однако в процедурной программе код разбросан. Предположим, мы имеем дело с геометрическими фигурами. Существует большая функция для рисования фигур, и она должна знать обо всех формах. Есть большая функция для поиска области, а другая для периметра. Код для круга разбросан по нескольким функциям, и для добавления другого типа фигуры нам нужно знать, какие функции нужно изменить. В объектно-ориентированной системе мы собираем функции в одну и ту же вещь ( class) с данными. Поэтому, если мы хотим посмотреть на весь код круга, он есть в Circleопределении, и если мы хотим добавить a, Quartercircleмы просто напишем его класс и у нас есть код.

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

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

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


3

У ОО есть много разных определений, да. Я уверен, что вы можете найти много из них самостоятельно. Мне лично нравится Rees Re: OO , чтобы понять их. Я предполагаю, что вы уже читали это, так как цитируете Пола Грэма. (Я рекомендую его всем, кто интересуется ОО.) Я собираюсь более или менее принять определение Java здесь {1,2,3,7,8,9}.

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

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

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

Java-iso OO - наполовину решение этих проблем, которое, как оказалось, выиграло конкурс популярности. Поскольку это тот же механизм, который люди Java применяют к мелкомасштабным задачам, создаваемым слабым языком, он начинает больше походить на волшебное решение всего, чем просто способ оставаться организованным. Люди, знакомые с функциональным программированием, склонны предпочитать другие решения, такие как классы типов CLOS или Haskell, или метапрограммирование шаблонов, когда застряли в C ++, или же (как я, ежедневно работающий в C #) использовать OO, но просто не волнуйтесь об этом ,


+1 - Отличный ответ. «Я не думаю, что ОО ужасно полезен в небольших масштабах».
Картик Сринивасан

Я даже прочитал статью ( dl.acm.org/citation.cfm?id=326103 ), в которой говорится, что ООП не показывает никаких реальных преимуществ в производительности по сравнению с процедурными для первых двух выпусков программного продукта. Насколько я понимаю, только начиная с третьего выпуска у вас есть реальные преимущества, потому что вы можете лучше повторно использовать / реорганизовывать код, написанный в ОО-стиле, чем в процедурном стиле.
Джорджио

1

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

  • Человек - это объект. У человека есть некоторые свойства, такие как возраст и пол. Человек может делать вещи: есть, спать, водить машину.
  • Автомобиль также является объектом (хотя и другого типа). У этого также есть свойства как марка, модель и год. Машина может делать вещи: двигаться.

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


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

1

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

ООП может быть понят (программистами) примерно за 90 секунд (см. Мой профиль для ссылки). Концепции очень просты.

Как применять это другое дело. То, что вы умеете раскачивать молоток, не означает, что вы знаете, как спроектировать и построить дом. ;-)


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

0

Некоторое время назад я написал сообщение в блоге, которое может оказаться полезным: объяснение процедурного и ООП .


Я не знаю, почему люди проголосовали за это! Эта статья лучше, чем все вышеперечисленное вместе! мой голос за +1
Харис

Его отвергли, потому что это просто связь, и это очень не рекомендуется. См. Вопрос meta stackoverflow: действительно ли ответы, которые содержат ссылки в других местах, действительно «хорошие ответы»?
icc97

0

То, как я впервые понял это:

До объектно-ориентированного программирования у вас было структурированное программирование . Все сосредоточено вокруг процесса. Первый вопрос, который вам нужно задать себе: « Что я хочу сделать с информацией? ».

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


0

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

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

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

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


-1

Я думаю, что страница Википедии - хорошее место, чтобы получить основы:
http://en.wikipedia.org/wiki/Object-oriented_programming

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

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

Надеюсь, это поможет. Просто продолжайте читать об этом и смотреть на код, и он внезапно "щелкнет". Это был мой опыт.


Уход Downvoter, чтобы дать причину?
RationalGeek

Похоже, что вы, вероятно, даже не прочитали весь заданный вопрос, а тем более заглянули в связанную запись блога. Насколько я могу судить, у автора нет проблем с основами. Так что, в основном, -1 за ответ на вопрос, который вы хотели ответить, а не на задаваемый вопрос.
Джесси Милликен
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.