В чем разница между процедурной программой и объектно-ориентированной программой? [закрытый]

Я довольно новичок в программировании, но я читал некоторые интересные дискуссии о StackOverflow о различных подходах к программированию. Я все еще не на 100% понимаю, в чем разница между процедурным и объектно-ориентированным программированием. Похоже, объектно-ориентированное программирование все еще использует процедуры (методы), но все организовано по-другому, потому что объект является звездой шоу. Но мне кажется, что процедуры все-таки позволяют делать все то же самое вещи. Как и в C, вы можете поместить все свои аналогичные процедуры в библиотеку. Не могли бы вы сказать, что библиотека в C похожа на объект в C++?

17 ответов


разница между ними тонкая, но существенная.

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

в объектно-ориентированной программе модули в виде объектов взаимодействуют путем отправки сообщений другим объектам.


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

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

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

n = n * 2

код здесь явно умножает n на 2 и сохраняет результат обратно в n.

способ OO сделать это-отправить" сообщение " объекту number, сообщая ему удвоить себя:

n.double();

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

С помощью OO вы создаете строковый объект, который также может принимать сообщение "double". Код для удвоения строки принадлежит объекту string, поэтому он знает, что он должен действовать по-разному с объектом number. Если бы он решил, что " bob "* 2 был "bobbob", код выглядел бы примерно так:

class number:                    class string:
    int n                           char array s
    procedure double:               procedure double:
        n = n * 2                       s = string_join(s,s)

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

и вы правы, библиотеку C можно сделать немного похожей на объекты. Классический пример stdio.h - ты никогда не заботишься что a FILE* на самом деле указывает только на то, что он будет вести себя определенным образом. The FILE*, fopen(), fclose() и другие функции класс сортов, представляющих возможности ввода/вывода в с.


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


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

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

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


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

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


ОО-это в основном установка ума. Вы можете запрограммировать OO на C (если вы действительно хотите ... ), и вы можете отлично иметь процедурный код на C++ / Java; я имею в виду, что даже если вы используете классы на поверхности, это все равно может быть процедурным.

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

все звучит философски, потому что это.

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

обновление
Как упоминалось в ответ Фланагана, OO языки реализуют конструкции, которые используют эту абстракцию.

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

вот пример OO в C


разница в том, что объекты имеют процедуры и связанные данные в одном и том же месте - процедурные языки используют "структуры" (вещи, которые держат связанные данные вместе), которые держат данные отдельно от процедур. Фактически все, что вы делаете на языке OO, должно быть возможно на процедурном языке с комбинацией структур и процедур.

основное различие-это набор ума, в который языки OO помещают программистов.


[извините за стиль праймера, уже поздно, и я устал]

процедуры обработки данных-данные в, применить некоторую обработку, получить данные из

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

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

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

шаблон для создания объектов называется класс; объект считается экземпляр класса

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

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

язык, который поддерживает объекты (через классы или нет) с передачей сообщений и наследованием, называется объектно-ориентированное. Если нет наследование, язык просто объектно-ориентированный.

удачи в учебе!


Procedural является частью процедурного / функционального / логического (или логически ориентированного) различия (сравните c, lisp и prolog) между различными способами описания того, что должна делать программа.

ориентация объекта ортогональна этой другой идее и описывает средство группировки подпрограмм с данными. C++ и java-процедурные языки с объектно-ориентированными функциями; fortran77-процедурные языки без объектно-ориентированных функций. Common lisp поддерживает ориентацию объектов; некоторые старшие шепелявят иначе. Простой ванильный пролог не поддерживает объекты, и я не могу назвать логически ориентированный язык, который делает (я не занимаюсь логически ориентированным программированием, он находится в моем списке вещей, которые нужно делать, когда я есть некоторые обильное свободное время. Я едва занимаюсь функциональным программированием).

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


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


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

ключевым различием между языком ассемблера и процедурным языком, таким как C или Pascal, является введение абстракции "процедура". Люди, пишущие ассемблерный код, создают процедуры, но его жесткий и подверженный ошибкам процедурный язык дает вам инструменты для облегчения.

разница между процедурным языком и языком OO, таким как C++, является "объектная" абстракция. Люди, которые пишут "c", часто создают концептуальные объекты но его трудно и ошибки склонны, язык OO дает вам инструменты, чтобы сделать его проще.

такие вещи, как петь# от Microsoft (или Erlang) добавьте абстракцию сообщения/процесса в язык. Конечно, вы можете передавать сообщения и создавать процессы в сборке, C или C++, но Sing# облегчает это.

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


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

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


разница составляет

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

пример : Pascal и C

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

пример : C++ и Java


Это упрощенный ответ.

  • в истинном языке OO единственное процедурное кодирование выполняется внутри объекта.

  • C не имеет объектов, а C++ - это язык, который поддерживает объекты. Java, с другой стороны, все является объектом(кроме примитивов). Все печатается.

  • Линейная прогрессия происходит внутри объектов, но сами объекты являются просто коллекциями кода и данные.

Это зависит от того, как вы определяете ООП. С точки зрения Java-подобных ООП, где вы вызываете методы на объектах, процедурное программирование почти то же самое. Насколько я могу сказать, вы можете эмулировать все принципы ООП (инкапсуляция, абстракция, полиморфизм, наследование) на процедурном языке, таком как C. доказательство этого GObject, в некоторой степени Objective-C и многие другие реализации языка ООП с использованием C, такие как cPython. Это делается с помощью структур и работает на этих структурах использование функций:

typedef struct {
    Object *isa;
    String *name;
    Date *birthday;
} Person;

Person *Person_new();
String *Person_name(Person *self);
void Person_setName(Person *self, String *newName);
// ...

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

class Person(object):
    def __init__(self):
        self._name = ""
        self._age = datetime.datetime.now()

    @property
    def name(self):
        return self._name

    @property
    def age(self):
        return self._age

Я выбрал Python для примера, потому что" self " является явным, как в Примере C. Многие языки ООП, такие как Java, абстрагируют это.

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

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

действительно, библиотека или, скорее, набор функций, работающих на структуре, совпадает с объектом в C++. На самом деле c++ реализован именно таким образом.


много интересных моментов тут уже писали.

процедурное программирование обычно не использует такое соединение данных и поведения в "объект". Я видел, как это делается в C раньше, но это было не очень красиво и слишком много обезьяньего бизнеса, чтобы приблизиться к тому, что можно сделать, скажем, с C++.

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

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

Это не полный, но это один аспект.


способ реализации C++ просто делает программирование OO похожим на процедурное программирование. Вам нужно немного изменить свое мышление.

в C++ объекты имеют методы, которые являются просто процедурами, которые действуют на объект. Но в реальном OO paradiam вы должны думать о методах как о потенциальных сообщениях, которые объект может получить (т. е. буквы). Объект получает сообщение (параметры представляют полезную нагрузку сообщения, т. е. содержимое письма) и изменяет его состояние основываясь на сообщении.


для довольно наглядного примера разницы между процедурным и OO попробуйте изучить Smalltalk. В Smalltalk все, и я имею в виду, что все является объектом. Нет операторов if или while-циклов. Вы достигаете этой функциональности, отправляя сообщения в (a.к. a. вызов методов on) другие объекты. Поначалу у тебя действительно кружится голова, но я думаю, ты быстро поймешь, что такое ОО.