方法vs功能vs程序


107

这个问题很简单,但是我经常听到这三个术语定义得如此残酷,但多年来我知道这些术语的含义有所不同。

“过程”,“方法”,“函数”,“子例程”等的“正确”定义是什么?


4
您放弃“常规”
mefisto

1
@teresko:我认为“子程序”更为常见。
mk12

Answers:


108

我在这里有一个不同的答案:实际上,实际上并没有什么区别,只是有一点例外,即“方法” 通常是指与OO语言中与对象关联的子例程。

术语“过程,函数,子例程,子程序和方法”实际上都具有相同的含义:较大程序中的可调用子程序。但是很难提出一个定义来捕获这些术语的所有变体用法,因为它们在各种编程语言或范式中使用的不一致。

您可能会说一个函数返回一个值。好吧,以下C函数不会返回值:

void f() { return; }

...但是我怀疑您会发现有人将其称为过程。

当然,在Pascal中,过程不会返回值,而函数会返回值,但这仅是Pascal设计方式的反映。在Fortran中,一个函数返回一个值,而子例程返回多个值。然而,这些都没有真正允许我们为这些术语提供一个“通用”定义。

实际上,术语“过程编程”是指一整类语言,包括C,Fortran和Pascal,其中只有一种实际上使用术语“过程”来表示任何东西。

因此,这些都不是真正一致的。唯一的例外可能是“方法”,它似乎几乎完全与OO语言一起使用,指代与对象关联的功能。虽然,但这并不总是一致的。例如,C ++通常使用术语“成员函数”而不是方法,(即使术语“方法”已在程序员中逐渐渗透到C ++语言中。)

关键是,这些都不是真正一致的。它只是反映了当时流行的任何语言所使用的术语。


这正是我以为的答案。(事后看来,我应该添加“子程序”作为另一个变体。)我可以问:为什么您找不到找到将C函数称为“过程”的人?是因为技术上不正确,还是因为“过程”一词目前不流行?
Django Reinhardt,2010年

7
C程序员使用术语“函数”仅仅是因为C的设计师使用了该术语。
Charles Salvia

15
让我们不要把婴儿和洗澡水一起扔出去。仅仅因为术语使用不完全一致,并不意味着不同的术语没有不同的含义。@Bruce和@Frank的定义是公认的,而不是特质的。含义不是通用的这一事实很重要,但这并不能证明“实际上,没有区别”这一飞跃是合理的。(@Django)
LarsH 2010年

9
C ++的对偶类型,将方法称为“成员函数”,而Java和C#则将函数称为“静态方法”。
约尔格W¯¯米塔格

2
如果您是编程新手,Bruce的答案肯定是您应该寻求的答案。他的定义在99%的时间内都是绝对正确的。但是我一直在寻找更多的技术/理论答案。有时,较新的程序员仅了解自己的领域,并坚持这就是全部。实际上,今天有一些工作的程序员仍然使用较旧的语言,并且使用不同的定义不是“错误的”。那是什么我最感兴趣的
的Django Reinhardt的

67

一个函数返回一个值,而是一个程序没有。

方法类似于函数,但是内部类的一部分。术语“ 方法”几乎专门用于面向对象的编程中。


8
不完全是内部的。方法是属于类的任何函数或过程。
Scott Whitlock,2010年

8
因此,SQL中的“存储过程”不会返回任何值吗?像Pascal这样的“程序”呢?您的定义是基于当前趋势还是应该被认为是通用定义?谢谢!
Django Reinhardt,2010年

3
@Django:在Pascal中,过程不能具有返回值,而函数必须具有返回值。在其他一些语言中,该术语的使用可能更宽松。
Bruce Alderman 2010年

1
FWIW,FORTRAN从早期开始就有SUBROUTINE和FUNCTION,区别是SUBROUTINE没有返回值。我不记得Pascal的起源于ALGOL。
David Thornley,2010年

2
@ 3p1c_d3m0n function在JS中同时扮演这两个角色当然是正确的,但是JS函数会全部返回。当return语句没有值时,该值是隐式的undefined。当没有return语句时,解释器将添加一个隐式return语句。也许很深奥,但这与此处给出的定义一致。这就是为什么var x = function() {}();在JS中合法的原因;如果不是隐式的回报,那将是一个错误,就像在Pascal中那样。
分号2015年

52

功能是一些把一束输入,并返回一个或多个值。如果返回的值完全由输入确定,并且该函数没有任何副作用(可能记录日志,或者导致其自身外部发生状态更改),则该函数称为纯函数。

一个方法是不返回值的函数。特别是,这意味着一个过程只能引起副作用。(这可能包括更改输入参数!)

方法是封闭在一组变量,即,一个功能关闭。它接受零个或多个输入参数,可以访问此变量集,并返回零个或多个值。在OO语言中,这些方法被附加到对象或类上。

在大多数主流的OO语言中,那些封闭的变量称为对象的成员字段或实例变量。方法可以是纯函数,不纯函数或过程。

后面的定义导致对象=结构+闭包的对应关系。


5
因此,对象是变量的集合以及这些公共变量的闭包的集合。基本上,面向对象的语言一直都有闭包,没人知道吗?有趣的观点!+1
乔治

1
我认为大多数方法都无法解决任何问题。foo.doSomething()不是无参数的。它具有一个参数(对象foo),并带有一些语法糖。闭包将能够引用其对象而无需此类参数。这并不是说方法不能是闭包,只是大多数不能,而且面向对象不足以使语言支持闭包。
2014年

3
foo.doSomething()关闭foo变量。中的任何语句都doSomething可以foo通过this或进行访问self,具体取决于您的语言。这就是“封闭”的定义。类关闭其成员变量,因此(忽略“ OO是什么”),OO就足够了。这在文献中是众所周知的...
Frank Shearar 2014年

1
呃没有。看到foo.前面的那一点foo.doSomething()吗?那是您传递doSomething()参数。仅仅因为它不在括号之间并不意味着它不是参数。方法中的thisor self内部仅是用于引用该参数的语法糖。
8bittree '16

1
@FrankShearar,我想说在计算中只有两个相当明显的区别:数据和指令。在(非常规)自修改代码的情况下,即使是这样,也是如此。在OO中,通常所说的“方法”(或“成员函数”)不必是您定义的方法或函数-所有这些常用的词实际上都是具有通用且可互换含义的同义词。您所暗示的“不纯函数”只是同一“指令”一般概念的另一个(也是最冗长的术语)。
史蒂夫

14

布鲁斯有一个很好的答案。我会在语义上添加:

  • 过程应该对参数“做某事”或引起其他副作用(例如printf
  • 函数应(a)回答有关参数的问题,或(b)根据参数计算新值
  • 函数方法应回答有关对象状态的问题
  • 过程方法应更改对象的状态

好答案!只是一个很小的补充:A procedure should "do something" to the arguments-或引起其他副作用(例如printf)。
Allon Guralnek,2010年

1
@Allon请注意,它printf返回一个值-打印的字符数-因此从技术上讲它是一个函数。
Sjoerd

@Sjoerd我不同意这printf是一个价值。它在调用范围之外有一个特定的副作用:即无论标准输出是什么,都应该是I / O。即使Scott并没有明确区分这种区别,在函数式编程中函数也不应该具有副作用,并且应该能够像回答返回的实际数据一样回答问题。
艾伦

4

上面有很好的详细答案;简短的故事是,它们将具有所有子程序风格;每个术语的含义将根据编程语言的上下文而有所不同

通常,函数返回一个值,但是它们不必

方法是目前通用的OOP术语

在SQL中,存储过程具有输出,但通常仅返回错误代码,而用户定义的函数必须返回值(可能是结果集)

同样,这些术语之间的确切区别取决于您正在和谁说话!


2

80%的熟练程度与对术语的熟悉程度直接相关,

95%的生产力是能够识别当前有用的功能,尽管用术语来描述它

我非常喜欢用c#调用它们的所有方法,除了在使用MSSQL时我们使用了sproc的时候,但是当然现在我们使用Postgres,它们被称为函数。


13
所有统计数据的83.5%是当场构成;-P
Django Reinhardt

1
我必须承认,当我听到有人在使用非OO语言工作时扔掉“方法”一词时,我会感到紧张。它似乎与运行非惯用代码密切相关。
Racheet 2014年

当我指的是C代码时,我使用“方法”,因为与我打交道的许多OO程序员在听术语“过程”或“函数”时都会精神崩溃。为了娱乐,如果我真的想弄乱它们,我可能会随机互换这些术语。它不好,有点像邀请一位
讲故事的人
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.