Метод против функции против процедуры

107

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

Каковы «правильные» определения «процедур», «методов», «функций», «подпрограмм» и т. Д.?

Джанго Рейнхардт
источник
4
Вы отказываетесь от "рутины"
mefisto
1
@teresko: Я думаю, что «подпрограмма» встречается чаще.
mk12

Ответы:

108

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

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

Вы могли бы сказать, что функция возвращает значение. Хорошо, следующая функция C не возвращает значение:

void f() { return; }

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

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

Фактически, термин «процедурное программирование» относится к целому классу языков, включая C, Fortran и Pascal, только один из которых фактически использует термин «процедура» для обозначения чего-либо.

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

Дело в том, что все это не соответствует действительности. Он просто отражает терминологию, применяемую теми языками, которые популярны в то время.

Чарльз Сальвиа
источник
Это именно то, что я думал, что ответ был. (Я должен был добавить «подпрограмму» в качестве другого варианта в ретроспективе.) Могу я спросить: почему бы вам не найти никого, кто бы назвал эту функцию C «процедурой»? Потому что это технически неправильно, или потому что термин «процедура» в настоящее время не в моде?
Джанго Рейнхардт
7
Программисты C используют термин «функция» просто потому, что разработчики языка C использовали этот термин.
Чарльз Сальвия
15
Давайте не будем выбрасывать ребенка с водой. Тот факт, что терминология не используется с полной согласованностью, не означает, что разные термины не имеют разного значения. Определения @ Брюса и @ Фрэнка широко признаны, а не уникальны. Тот факт, что значения не являются универсальными, важен, но он не оправдывает скачок к «практически говоря, разницы нет». (@Django)
LarsH
9
Вид двойственного к C ++, который вызывает методы «функции-члены», Java и C # вызывают функции «статические методы».
Йорг Миттаг
2
Ответ Брюса, безусловно, тот, на который вам стоит пойти, если вы новичок в программировании. Его определения будут абсолютно правильными в 99% случаев. Но я искал больше технического / теоретического ответа. Иногда новые программисты знают только свой домен и настаивают на том, что это все, что есть. На самом деле сегодня работают программисты, которые до сих пор используют более старые языки и не ошибаются в использовании разных определений. Это было то, что меня больше всего интересовало.
Джанго Рейнхардт
67

Функция возвращает значение, но процедура не делает.

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

Брюс Олдерман
источник
8
Не совсем внутренний. Метод - это любая функция или процедура, которая является частью класса.
Скотт Уитлок
8
Таким образом, «хранимая процедура» в SQL не возвращает никаких значений? А как насчет «процедуры» в чем-то вроде Паскаля? Основаны ли ваши определения на современных тенденциях или они должны рассматриваться как универсальные определения? Спасибо!
Джанго Рейнхардт
3
@Django: в Паскале процедура не может иметь возвращаемого значения, а функция должна иметь возвращаемое значение. В некоторых других языках терминология может использоваться более свободно.
Брюс Олдерман
1
FWIW, FORTRAN имел субпрограммы и функции с ранних дней, разница в том, что субпрограмма не возвращала значение. Я не помню об Алголе, от которого произошел Паскаль.
Дэвид Торнли
2
@ 3p1c_d3m0n Это, безусловно, верно, что functionвыполняет обе роли в JS, но все функции JS возвращают. Когда оператор возврата не имеет значения, значение является неявным undefined. Когда оператор return отсутствует, интерпретатор добавляет неявный оператор return. Эзотерически, возможно, но это согласуется с определением, данным здесь. Вот почему var x = function() {}();законно в JS; если не для неявных возвратов, это должно быть ошибкой, как это было бы в Паскале.
точка с запятой
52

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

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

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

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

Последнее определение приводит к соответствию object = struct + .

Фрэнк Шиарар
источник
5
Таким образом, объект - это набор переменных и набор замыканий над этими общими переменными. По сути, у объектно-ориентированных языков всегда были замыкания, и никто не знал? Интересный вид! +1
Джорджио
1
Я не верю, что большинство методов близко к чему-либо. foo.doSomething()не без параметров. У него есть один параметр (объект foo) с заданным синтаксическим сахаром. Замыкание сможет ссылаться на свой объект, не нуждаясь в таком параметре. Это не значит, что методы не могут быть замыканиями, просто этого не происходит, а того, что OO недостаточно для того, чтобы язык поддерживал замыкания.
8bittree
3
foo.doSomething()закрывает по fooпеременной. Любое заявление в doSomethingможет получить доступ fooчерез thisили self, в зависимости от вашего языка. Это само определение «близко». Классы закрывают свои переменные-члены, поэтому (игнорируя «что такое OO»), OO достаточно. Это довольно хорошо известно в литературе ...
Фрэнк Шиарар
1
Э, нет Видите это немного foo.впереди foo.doSomething()? Это вы передаете doSomething()параметр. То, что это не между скобками, не означает, что это не параметр. Метод внутри thisили selfвнутри является просто синтаксическим сахаром для ссылки на этот параметр.
8bittree
1
@FrankShearar, я бы сказал, что в вычислениях есть только два достаточно четких различия - данные и инструкции. Даже это выходит из окна в (необычном) случае самоизменяющегося кода. В ОО то, что обычно называют «методом» (или «функцией-членом»), не обязательно должно быть методом или функцией по вашему определению - все эти слова в общем использовании являются синонимами общего и взаимозаменяемого значения. «Нечистая функция», о существовании которой вы намекаете, - это просто еще один (а также самый многогранный и жаргонистический) синоним того же общего понятия «инструкции».
Стив
14

У Брюса хороший ответ . Я бы добавил, семантически:

  • Процедура должна «что-то делать» с аргументами или вызывать какой-то другой побочный эффект (например printf)
  • Функция должна (а) ответить на вопрос об аргументах или (б) вычислить новое значение на основе аргументов
  • Функциональный метод должен ответить на вопрос о состоянии объекта
  • Метод процедуры должен изменить состояние объекта
Скотт Уитлок
источник
Отличный ответ! Только одно крошечное дополнение: A procedure should "do something" to the arguments- или вызвать другой побочный эффект (например printf).
Аллон Гуралнек
1
@Allon Обратите внимание, что printfвозвращает значение - количество напечатанных символов - так что это технически функция.
Sjoerd
@ Шоерд Я не согласен, что printfэто ценность. У него был специфический побочный эффект, выходящий за рамки его вызова: а именно ввод / вывод для любого стандартного вывода, которым он должен быть. Несмотря на то, что Скотт не указал это различие, функции функционального программирования не должны иметь побочных эффектов и должны иметь возможность отвечать на вопросы, как если бы у вас были реальные данные, которые он возвращает.
Алан
4

хорошие подробные ответы выше; Короче говоря, все они будут подпрограммами; что подразумевается под каждым термином, будет варьироваться в зависимости от контекста языка программирования

в общем случае функции возвращают значение, но им не нужно

методы являются общими терминами ООП в настоящее время

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

Опять же, точное различие между этими терминами зависит от того, с кем вы разговариваете!

Стивен А. Лоу
источник
2

80% владения языком напрямую связаны со знакомством с номенклатурой,

95% производительности - это способность определить, что полезно в данный момент, несмотря на термины, используемые для его описания.

Я предпочитаю вызывать их все методы в c #, за исключением тех случаев, когда я использовал MSSQL, у нас были sproc, но, конечно, теперь мы используем Postgres, и они называются функциями.

MvcCmsJon
источник
13
83,5% всей статистики составляется на месте ;-P
Джанго Рейнхардт
1
Должен признаться, я нервничаю, когда слышу, как кто-то разбрасывается термином «метод» при работе на языке, отличном от ОО. Кажется, это сильно коррелирует с запуском неидиоматического кода.
Рашит
Я использую «Метод» при обращении к коду C, потому что у многих программистов ОО, с которыми я сталкиваюсь, есть умственное расстройство при прослушивании терминов процедура или функция. Ради интереса, если я действительно хочу поиграть с ними, я мог бы случайно поменять их местами. Это нехорошо, вроде как пригласить полтергейста в свой дом ... :)
mattnz