方法和函数有什么区别?


1739

有人可以在OOP上下文中提供方法功能的简单说明吗?



12
当属性的值是一个函数时,我们称它为方法
编码器

2
方法的反义词是什么?那是我的问题。“功能”是父概念。方法是一种功能。不是方法但可以直接通过名称调用的函数类型的名称是什么?
亚历山大·米尔斯

看到另一个概述r中方法和函数之间差异的解释将很有趣。有趣的是方法通常会包含一个函数。如果方法是一个与对象有关的函数,那么对象类的函数检查if(class(object)) { ... } else {stop()}在概念上就等于方法?
Konrad

正确的术语确实可以取决于语言,因此在不同的上下文中它可能意味着稍有不同的事物。即使这样,由于使用一种语言而不是另一种语言的程序员更习惯于某些术语。程序员还受到其同事使用术语(无论正确与否)的影响。这些术语经常互换使用。例如,请参阅下面的一些评论。
jvriesem

Answers:


1830

函数是一段代码由名字叫做。可以传递数据以对其进行操作(即参数),还可以选择返回数据(返回值)。传递给函数的所有数据都被显式传递。

方法是一段代码,由与对象相关联的名称叫。在大多数方面,它与功能相同,但有两个主要区别:

  1. 方法被隐式传递给调用该方法的对象。
  2. 方法能够对类中包含的数据进行操作(记住,对象是类的实例-类是定义,对象是该数据的实例)。

(这是一个简化的解释,忽略了范围问题等。)


249
对于1),您还应该添加C ++中的方法称为成员函数。因此,在这种情况下,函数和方法之间的差异类似于C ++中函数和成员函数之间的差异。此外,像Java这样的语言仅具有方法。在这种情况下,函数将类似于静态方法,而方法将具有相同的含义。对于2),您应该添加一个方法能够对声明为该类的一部分的私有实例(成员)数据进行操作。任何代码都可以访问公共实例数据。
拉菲·哈

45
函数是数学构造。我会说所有方法都是函数,但并非所有函数都是方法
Tyler Gillies

28
来自函数式编程的背景,我觉得函数和方法之间存在着深刻的区别。主要是方法有副作用,该函数应该是纯函数,因此具有相当好的参照透明性
HHC 2013年

26
@TylerGillies和HHC,我同意,如果“功能”和“方法”表示您想要它们的含义,那可能会很好,但是您的定义未反映这些术语的某些非常常用的用法。
Paul Draper

9
按照这个定义,不是因为静态方法与特定实例没有任何关系,也不是将静态方法视为实际方法吗?
Carcigenicate

961

方法在对象上。
功能独立于对象。

对于Java和C#,只有方法。
对于C,只有功能。

对于C ++和Python,这取决于您是否在课堂上。


39
现在该添加C#了。
Rosdi Kasim 2014年

7
@RosdiKasim对于C#,只有方法。(因为甚至静态方法都需要与对象相关联)
Lynn Crumbling 2014年

38
类中的静态方法如何?这些将独立于对象(在Java中)。那不是函数吗?
Squeazer 2014年

12
@Squeazer最近有一个关于stackoverflow.com/questions/30402169/…的问题。Java语言规范将它们区别为“类方法”(静态)和“实例方法”。因此,它们仍然是所有方法。
xji 2015年

13
Java有lambda表达式,它们是没有方法的功能
最大Heiber

228

“方法”“功能”的面向对象的单词。这几乎就是它的全部(即,没有真正的区别)。

不幸的是,我认为这里的许多答案可以使存在某些复杂的,有意义的差异的想法永存或发展。

真的-并没有那么多,针对同一件事只是不同的用词。

[后期补充]


实际上,正如Brian Neal在对此问题的评论中指出的那样,C ++标准在引用成员函数时从不使用术语“方法”。有人可能会认为这表明C ++并不是真正的面向对象的语言。但是,我更倾向于将其作为一种指示,即相当聪明的一群人认为没有特别强烈的理由使用另一个术语。


14
方法是一种特殊的函数类型,带有传递的隐式参数(定义该方法的类的实例)。严格来说,这很重要,因为函数不应使用或修改参数列表中未包含的任何内容。
ty1824 2014年

4
@ ty1824并非总是将方法传递给隐式参数。在Python中,该self参数是显式的。许多语言都有静态方法,这些方法没有传递实例。
Max Heiber

1
@mheiber这些是有效点。关于自我,您是正确的,它是明确定义的。关键是基于原始对象引用,该调用是隐式的。有些语言支持重写a thisself,但是这些构造通常被称为函数,而不是方法。
ty1824 '16

1
@mheiber就静态方法而言-java将它们实现为一种解决方法,因此可以在不需要上下文的情况下实现功能。我可能会建议“静态方法”是一个令人误解的术语,应该在理想的理论世界中替换:)
ty1824'1

1
@ ty1824 C ++,Scala,Python,Ruby,JavaScript和Scala都有静态方法,因此我认为这不仅仅是Java。我也不喜欢它们:它们相当于使用对象(状态束),就像它们是名称空间一样。
Max Heiber

99

通常,方法是属于类的函数,函数可以在代码的任何其他范围内,因此您可以声明所有方法都是函数,但并非所有函数都是方法:

以以下python示例为例:

class Door:
  def open(self):
    print 'hello stranger'

def knock_door:
  a_door = Door()
  Door.open(a_door)

knock_door()

给定的示例向您显示了一个名为“ Door”的类,该类具有一个称为“ open”的方法或动作,由于它是在类内声明的,因此称为“方法”。在代码的下面还有另一部分“ def”定义了一个函数,它是一个函数,因为它没有在类中声明,您可以看到该函数调用在类中定义的方法,最后该函数被自己叫。

如您所见,您可以在任何地方调用函数,但如果要调用方法,则必须传递与声明该方法的类相同类型的新对象(Class.method(object)),或者必须调用对象内部的方法(object.Method()),至少在python中。

将方法视为只有一个实体可以做的事情,因此,如果您有一个Dog类,则仅在该类内部具有树皮函数是有意义的,那将是一种方法;如果您也具有Person类,则对写一个不属于任何类别的函数“ feed”,因为人类和狗都可以被喂食,而您可以调用该函数,因为它特别不属于任何类别。


2
到目前为止,这个答案(主要是第一句话)是该问题最简洁,总体上最好的答案。
yourcomputergenius

61

记住的简单方法:

  • ˚F油膏→ ˚F REE(免费意味着不属于一个对象或类)
  • 中号 ethod→中号余烬(对象或类的一个成员)

由于通常可以互换,所以为什么需要助记符?
Sapphire_Brick

44

关于函数方法之间主要区别的一个非常笼统的定义:

函数是在类外部定义的,而方法是在类内部和部分的内部定义的。


30

如果您想在这里阅读“我对OO方法的介绍”

面向对象范例背后的思想是“威胁”该软件由..好“对象”组成。现实世界中的对象具有属性,例如,如果您有一个雇员,该雇员有一个姓名,一个雇员ID,一个职位,他属于某个部门等,等等。

该对象还知道如何处理其属性并对其执行一些操作。假设我们想知道某个员工现在在做什么,我们会问他。

employe whatAreYouDoing.

“ whatAreYouDoing”是发送给对象的“消息”。对象知道如何回答该问题,据说它具有解决该问题的“方法”。

因此,对象必须公开其行为的方式称为方法。因此,方法是工件对象必须“做”某事。

其他可能的方法是

employee whatIsYourName
employee whatIsYourDepartmentsName

等等

另一方面,函数是编程语言计算某些数据的方式,例如,您可能具有返回16的函数addValues(8,8)

// pseudo-code
function addValues( int x, int y )  return x + y 
// call it 
result = addValues( 8,8 )
print result // output is 16...

由于第一种流行的编程语言(例如fortran,c,pascal)并未涵盖OO范式,因此它们仅将这些工件称为“函数”。

例如,C中的先前函数为:

int addValues( int x, int y ) 
{
   return x + y;
}

说一个对象具有执行某项操作的“功能”并不是“自然”的事情,因为功能与数学相关,而员工对此几乎没有数学知识,但是您可以使用与功能完全相同的方法,例如在Java中,这将是等效的addValues函数。

public static int addValues( int x, int y ) {
    return x + y;
}

看起来很熟悉?那是因为Java起源于C ++,C起源于C。

最后只是一个概念,在实现中它们可能看起来相同,但是在OO文档中,这些称为方法。

这是Java中以前的Employee对象的示例。

public class Employee {

    Department department;
    String name;

    public String whatsYourName(){
        return this.name;
    }
    public String whatsYourDeparmentsName(){
         return this.department.name();
    }
    public String whatAreYouDoing(){
        return "nothing";
    } 
    // Ignore the following, only set here for completness
    public Employee( String name ) {
        this.name = name;
    }

}

// Usage sample.
Employee employee = new Employee( "John" ); // Creates an employee called John

// If I want to display what is this employee doing I could use its methods.
// to know it.
String name = employee.whatIsYourName():
String doingWhat = employee.whatAreYouDoint();

// Print the info to the console.

 System.out.printf("Employee %s is doing: %s", name, doingWhat );

Output:
Employee John is doing nothing.

区别在于应用它的“域”上。

AppleScript具有“自然语言”的概念,这在OO上已经有了。例如Smalltalk。我希望您阅读此书后,可能更容易理解对象中的方法。

注意:该代码不是要编译,仅作为示例。随时修改帖子并添加Python示例。


3
太棒了!关于方法如何成为对象命令的精彩论述。这是理解OO的关键,并且您在此答案中缺乏措辞,这就是为什么OO在当今行业中如此被滥用的原因。优秀的职位。
moffdub

18

在OO世界中,两者通常用来表示同一件事。

从纯Math和CS的角度来看,使用相同的参数(f(x,y)=(x + y))调用时,函数将始终返回相同的结果。另一方面,方法通常与类的实例相关联。同样,大多数现代OO语言在很大程度上不再使用术语“功能”。许多静态方法可以像函数一样,因为它们通常没有状态(并不总是为真)。


17

假设一个函数是一块代码块(通常具有自己的作用域,有时带有自己的闭包),可以接收一些自变量并且还可以返回结果。

方法是对象所拥有的功能(在某些面向对象的系统中,更确切地说它是类所拥有的)。被对象/类“拥有”意味着您通过对象/类来引用该方法。例如,在Java中,如果要调用对象“门”拥有的方法“ open()”,则需要编写“ door.open()”。

通常,方法还会获得一些额外的属性来描述它们在对象/类中的行为,例如:可见性(与封装的面向对象概念有关),它定义了可以从哪些对象(或类)调用该方法。

在许多面向对象的语言中,所有“功能”都属于某个对象(或类),因此在这些语言中,没有不属于方法的功能。


1
我很困惑,方法可能归对象或类所有,因为Javascript(您在问题中提到的)是一种语言,它具有对象而非类所拥有的方法,从而逆转了面向对象语言的普遍趋势(尽管结构类似于类)。
Mike Tunnicliffe


13

函数是数学概念。例如:

f(x,y) = sin(x) + cos(y)

表示函数f()将返回添加到第二个参数的余弦值的第一个参数的正弦值。这只是数学。碰巧sin()和cos()也是函数。函数具有另一个属性:对具有相同参数的函数的所有调用应返回相同的结果。

另一方面,方法是与面向对象语言中的对象相关的功能。它有一个隐式参数:作用于对象(及其状态)。

因此,如果您的对象Z具有方法g(x),则可能会看到以下内容:

Z.g(x) = sin(x) + cos(Z.y)

在这种情况下,与前面的函数示例相同,将传入参数x。但是,cos()的参数是一个位于对象Z内的值。Z和其内的数据(Zy)是Z的g()方法的隐式参数。


13

函数或方法是一段可命名的可调用代码,它执行一些操作并有选择地返回一个值。

C语言中,使用术语功能。JavaC#人士会说它是一种方法(在这种情况下,函数是在类/对象中定义的)。

C ++程序员可以称之为一个函数或有时方法(取决于如果他们写程序风格的C ++代码或正在做的C面向对象的方式++,还有C / C ++只是程序员可能会调用它的函数,因为术语“方法”是在C / C ++文献中较少使用)。

您可以通过调用函数的名称来使用它,例如,

result = mySum(num1, num2);


您可以通过先引用对象来调用方法,例如,

result = MyCalc.mySum(num1,num2);

13

从历史上看,“方法”是不返回值的东西,而“功能”是不返回值的东西,可能会有细微的差别。每种语言都有其自己具有特殊含义的术语词典

“ C”中,单词“功能”表示程序例程

Java中,术语“函数”没有任何特殊含义。而“方法”是指构成类的实现的例程之一。

C#中,它将转换为:

public void DoSomething() {} // method
public int DoSomethingAndReturnMeANumber(){} // function

但实际上,我重申,这两个概念确实没有区别。如果您在有关Java的非正式讨论中使用“功能”一词,人们会认为您的意思是“方法”并继续下去。不要在有关Java的适当文档或演示文稿中使用它,否则会显得很愚蠢。


实际上,在您的示例中,两者都是method...或我将其称为procedurefunction
Yousha Aleayoub

9

函数是一组可用于处理数据的逻辑。

而Method是用于处理其所属对象的数据的函数。从技术上讲,如果您有一个与您的类不完全相关但在类中声明的函数,则它不是方法;这称为不良设计。


8

类上的方法作用于该类的实例(称为对象)。

class Example
{
   public int data = 0; // Each instance of Example holds its internal data. This is a "field", or "member variable".

   public void UpdateData() // .. and manipulates it (This is a method by the way)
   {
      data = data + 1;
   }

   public void PrintData() // This is also a method
   {
      Console.WriteLine(data);
   }
}

class Program
{
   public static void Main()
   {
       Example exampleObject1 = new Example();
       Example exampleObject2 = new Example();

       exampleObject1.UpdateData();
       exampleObject1.UpdateData();

       exampleObject2.UpdateData();

       exampleObject1.PrintData(); // Prints "2"
       exampleObject2.PrintData(); // Prints "1"
   }
}

8

在诸如对象Pascal或C ++之类的OO语言中,“方法”是与对象关联的功能。因此,例如,“狗”对象可能具有“吠叫”功能,因此将其视为“方法”。相反,“ StrLen”函数是单独存在的(它提供了作为参数提供的字符串的长度)。因此,它只是一个“功能”。从技术上讲,JavaScript也是面向对象的,但是与成熟的语言(如C ++,C#或Pascal)相比,JavaScript面临许多限制。尽管如此,区别仍然应保持。

还有两个事实:C#是完全面向对象的,因此您不能创建独立的“函数”。在C#中,每个函数都绑定到一个对象,因此从技术上讲,它是一种“方法”。更重要的是,在C#中很少有人将它们称为“方法”-他们只是使用术语“函数”,因为没有任何真正的区别。

最后,Pascal专家也区分了“函数”(返回值)和“过程”(不返回),以使任何Pascal专家都不会在这里碰到我。尽管您可以选择是否返回值,但是C#并未明确区分这种区别。


8

自从您提到Python之后,以下内容可能是大多数现代面向对象语言中方法与对象之间关系的有用说明。简而言之,他们所谓的“方法”只是一个传递了额外参数的函数(正如其他答案所指出的那样),但是Python比大多数语言都更加明确。

# perfectly normal function
def hello(greetee):
  print "Hello", greetee

# generalise a bit (still a function though)
def greet(greeting, greetee):
  print greeting, greetee

# hide the greeting behind a layer of abstraction (still a function!)
def greet_with_greeter(greeter, greetee):
  print greeter.greeting, greetee

# very simple class we can pass to greet_with_greeter
class Greeter(object):
  def __init__(self, greeting):
    self.greeting = greeting

  # while we're at it, here's a method that uses self.greeting...
  def greet(self, greetee):
    print self.greeting, greetee

# save an object of class Greeter for later
hello_greeter = Greeter("Hello")

# now all of the following print the same message
hello("World")
greet("Hello", "World")
greet_with_greeter(hello_greeter, "World")
hello_greeter.greet("World")

现在比较一下函数greet_with_greeter和方法greet:唯一的区别是第一个参数的名称(在函数中我称之为“ greeter”,在方法中我称之为“ self”)。因此,我可以使用与greet使用greet_with_greeter函数完全相同的方法来使用该方法(因为我在类中定义了它,因此使用了“点”语法):

Greeter.greet(hello_greeter, "World")

因此,我已经有效地将方法变成了函数。我可以将函数转换为方法吗?好吧,由于Python使您可以在定义类后将它们弄乱,因此请尝试:

Greeter.greet2 = greet_with_greeter
hello_greeter.greet2("World")

是的,该函数greet_with_greeter现在也称为method greet2。这显示了方法和函数之间的唯一真正区别:当您通过调用object.method(args)在对象上“调用”方法时,语言将其神奇地变成了method(object, args)

(OO纯粹主义者可能会认为方法不同于函数,并且,如果您进入高级Python或Ruby或Smalltalk !,您将开始明白它们的用处。某些语言还使方法可以对对象的某些位进行特殊访问。但是主要的概念差异仍然是隐藏的多余参数。)


7

对我来说:如果我同意:方法的功能和函数的功能是相同的:

  • 一个函数可能返回一个值
  • 可能期望参数

就像任何一段代码一样,您可能要放入对象,结果可能会有对象。在这样做的过程中,它们可能会更改对象的状态,但不会更改它们的基本功能。

对象或其他代码的调用函数可能存在定义差异。但这不是语言区别的原因,这就是人们互换它们的原因吗?我会小心地提到计算示​​例。因为我雇用了员工来进行计算:

new Employer().calculateSum( 8, 8 );

通过这种方式,我可以依靠雇主负责计算。如果他想要更多的钱,我就释放他,让垃圾收集员处理未使用的雇员的职能剩下来,然后再找一个新雇员。

即使争论一个方法是一个对象函数而一个函数是未连接的计算对我也没有帮助。函数描述符本身以及理想情况下的函数文档将告诉我它需要什么以及它可能返回什么。其余的,比如操纵某些对象的状态,对我来说并不是真正透明的。我确实希望函数和方法都可以交付和操纵他们所要求的内容,而无需详细了解他们是如何做到的。即使是纯计算功能也可能会更改控制台的状态或附加到日志文件。


5

让我们不要过于复杂,这应该是一个非常简单的答案。方法和功能是同一回事。当函数在类外部时,可以将其称为函数,而在类内部写入函数时,可以将其称为方法。


4

根据我的理解,方法是可以在类上执行的任何操作。它是编程中的通用术语。

在许多语言中,方法由函数和子例程表示。大多数语言为此使用的主要区别在于,函数可以将值返回给调用者,而子例程则不能。但是,许多现代语言仅具有函数,但是这些函数可以选择不返回任何值。

例如,假设您想描述一只猫,并且希望它能打哈欠。您将创建一个带有Yawn方法的Cat类,该方法很可能是没有任何返回值的函数。


4

对于一阶近似而言,方法(C ++风格OO)是成员函数的另一个词,该成员函数是类的一部分。

在像C / C ++这样的语言中,您可以具有一些不是类成员的函数;您不会将与类无关的函数称为方法。


4

函数是主要属于面向过程的编程的概念,其中函数是可以处理数据并返回值的实体

方法是概念 面向对象编程其中方法是类的成员,该类主要对类成员进行处理。


3

恕我直言,人们只是想发明一个新词来简化程序员在引用对象内部函数时的通信。

如果您说的是方法,则意味着在类内部使用函数。如果您说的是函数,则意味着仅是课堂外的函数。

事实是两个词都用来描述功能。即使您错误地使用了它,也不会发生任何错误。这两个词很好地描述了您想要在代码中实现的目标。

函数是一种代码,它必须起某些作用(一个函数)。方法就是方法解决问题的。

它做同样的事情。是同一回事。如果您想要超精确并遵循约定,则可以将方法作为对象内部的函数进行调用。


2

我不是专家,但这是我所知道的:

  1. 函数是C语言术语,指的是一段代码,函数名称将是使用此函数的标识符。

  2. 方法是OO术语,通常在功能参数中具有this指针。您不能像C那样调用这段代码,需要使用object来调用它。

  3. 调用方法也不同。在这里调用含义来找到这段代码的地址。C / C ++,链接时间将使用功能符号定位。

  4. Objecive-C是不同的。调用的含义是C函数使用数据结构查找地址。这意味着在运行时一切都是已知的。


2

我知道许多其他人已经回答了,但是我发现以下是一个简单而有效的单行答案。尽管它看起来并不比其他答案好很多,但是如果您仔细阅读,它具有方法与函数有关的所有知识。

方法是具有定义的接收方的函数,按OOP术语,方法是对象实例上的函数。


2

方法和功能之间的差异

通过阅读有关Microsoft的文档

包含可执行代码的成员统称为类的函数成员。上一节介绍了方法,它们是函数成员的主要种类。本节描述了C#支持的其他类型的函数成员:构造函数,属性,索引器,事件,运算符和终结器。

因此,方法是功能的子集。每个方法都是一个函数,但并非每个函数都是一个方法,例如,constructor不能说是一个方法,而是一个函数。


属性,索引器和事件不是函数。getter,setter(用于属性和索引器),加法器和移除器(用于事件)是函数。函数成员是与一个或多个函数关联的成员,但不一定是某个函数。
乔恩·汉纳

2

函数-独立代码中的函数,其中包含一些逻辑,必须独立调用 并在类外部定义。

方法-方法是一段独立的代码,它参考某个对象而调用,并在类内部定义。


您如何在静态类(也就是静态类)中调用一段代码,这是方法还是函数?静态函数/类的方法并不需要它在声明的类的对象。
沃尔夫冈·罗斯

1

这是一些使用JavaScript示例的方法与函数的解释:

test(20, 50); 是函数定义,用于运行某些步骤或返回可以存储/在某处使用的内容。

您可以重用代码:一次定义代码并多次使用。

您可以将同一代码多次使用不同的参数,以产生不同的结果。

var x = myFunction(4, 3);   // Function is called, return value will end up in x

function myFunction(a, b) {
    return a * b;          // Function returns the product of a and b
}

var test = something.test(); 这里的test()可以是某些对象的方法,也可以是为内置对象自定义定义的原型,这里是更多的解释:

JavaScript方法是可以对对象执行的操作。

JavaScript方法是包含函数定义的属性。

javascript中字符串的内置属性/方法:

var message = "Hello world!";
var x = message.toUpperCase();
//Output: HELLO WORLD!

自定义示例:

function person(firstName, lastName, age, eyeColor) {
    this.firstName = firstName;  
    this.lastName = lastName;
    this.age = age;
    this.eyeColor = eyeColor;
    this.changeName = function (name) {
        this.lastName = name;
    };
}

something.changeName("SomeName"); //This will change 'something' objject's name to 'SomeName'

您还可以定义String,Array等的属性

String.prototype.distance = function (char) {
    var index = this.indexOf(char);

    if (index === -1) {
        console.log(char + " does not appear in " + this);
    } else {
        console.log(char + " is " + (this.length - index) + " characters from the end of the string!");
    }
};

var something = "ThisIsSomeString"

// now use distance like this, run and check console log

something.distance("m");

一些参考:Javascript对象方法函数有关原型的更多信息


请不要针对多个问题发布相同的答案。发表一个好的答案,然后投票/标记以将其他问题重复作为一个重复。如果问题不是重复的,请定制问题的答案。
Paul Roub

感谢您的反馈,我没有定制其他答案,因此删除了该问题。:-)
Lahar Shah

1

TL; DR

函数是要运行的一段代码。
方法是对象内部的函数。

函数示例:


function sum(){
  console.log("sum")l
}

方法示例:

const obj = {
a:1,
b:2,
sum(){
  }
}

这就是为什么我们说函数内的“ this”关键字不是很有用,除非我们将其与call,apply或bind一起使用..因为call,apply,bind会将该函数作为object ==>内部的方法来调用将函数转换为方法


1

它们通常是可互换的,但是方法通常引用类内部的子例程,而函数通常引用类外部的子例程。例如,在Ruby中:

# function
def putSqr(a)
   puts a ** 2
end


class Math2
   # method
   def putSqr(a)
      puts a ** 2
   end
end

在Java中,所有内容(package和import语句除外)都必须在类内部,人们几乎总是将它们称为“方法”。

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.