方法和函数有什么区别?

2149

能否简单解释一下在面向对象编程中方法函数的区别?


看到另一种解释来阐述 [tag:r] 中方法和函数的区别会很有趣。这很有趣,因为方法通常会包含一个函数。如果方法是一个依赖于对象的函数,那么检查对象类别的函数 if(class(object)) { ... } else {stop()} 在概念上等同于方法吗? - Konrad
1
适当的术语可能因语言而异,在不同的上下文中可能略有不同的含义。即便如此,由于程序员在使用一种语言时更习惯于某些术语,因此他们会受到同事使用术语的影响(无论其是否正确)。这些术语通常可以互换使用。例如,请参见以下一些评论。 - jvriesem
关于概念混淆的问题提得非常好。我喜欢程序员们的哲学意识。谢谢大家。 - Berkay
42个回答

2223

函数是通过名称调用的代码片段。它可以传递要操作的数据(即参数),并可以选择性地返回数据(返回值)。所有传递给函数的数据都是明确传递的。

方法是通过与对象关联的名称调用的代码片段。在大多数方面,它与函数相同,除了两个关键区别:

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

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


297
  1. 你还应该补充说明,C++中的函数被称为成员函数。因此,在这个背景下函数和方法之间的区别类似于C++中函数和成员函数的区别。此外,像Java这样的语言只有方法。在这种情况下,函数类似于静态方法,而方法则具有相同的含义。
  2. 你应该补充说明,一个方法能够操作作为类的一部分声明的私有实例(成员)数据。任何代码都可以访问公共实例数据。
- khatchad
68
函数是一种数学构造。我会说所有的方法都是函数,但并非所有的函数都是方法。 - Tyler Gillies
39
作为一个有函数式编程背景的人,我感觉函数和方法之间有很深的区别。主要是方法会产生副作用,而函数应该是纯函数,从而具有引用透明性这一不错的特性。 - HHC
39
@TylerGillies和HHC,我同意如果“function”和“method”的含义符合你们的期望会很好,但是你们的定义并没有反映出这些术语的一些常见用法。 - Paul Draper
17
按照这个定义,一个静态方法不应该被认为是一个方法,因为它与特定的实例没有关系,您同意吗? - Carcigenicate
显示剩余10条评论

1106

一个方法是属于对象的或者静态的属于类的。
一个函数则是独立于任何对象(并且在任何类之外)。

对于Java和C#,只有方法存在。
对于C语言,只有函数存在。

对于C++和Python,则要看你是否在一个类中使用。
但用基础英语来说:

  • 函数:独立的特征或功能。
  • 方法:一种做某事的方式,有不同的方法或途径,但涉及相同的方面(也称作类)。

42
类中的静态方法呢?它们不依赖于对象(在Java中),难道不就相当于函数吗? - Squeazer
5
在Scala中:函数,可以通过一组参数列表来调用,并生成结果。函数拥有参数列表、主体和返回类型。属于类、特征或单例对象的函数称为方法。定义在其他函数内部的函数称为局部函数。返回类型为Unit的函数称为过程。源代码中的匿名函数称为函数字面量。运行时,函数字面量被实例化为称为函数值的对象。 - Bob
14
最近有一个关于此问题的问题:https://dev59.com/l10a5IYBdhLWcg3wYXu8。 Java语言规范将它们区分为“类方法”(静态)和“实例方法”。所以它们仍然都是方法。 - xji
18
Java有lambda表达式,它们是非方法的函数。 - Max Heiber
3
Python中有方法和函数。 - Ali Yousefi
显示剩余9条评论

327
"'method'是面向对象编程中'function'的词汇。实际上,它们没有真正的区别,只是同一概念的不同称呼。很遗憾,我认为这里许多答案在推崇或提升这种复杂而有意义的差异观念。

事实上,它们之间并没有太大区别,只是相同概念的不同表述。

[晚期添加]


实际上,正如Brian Neal在对此问题的评论中指出的那样,C++标准在涉及成员函数时从未使用过术语“method”。某些人可能会将其视为C++不是真正的面向对象语言的迹象;然而,我更愿意将其视为一群相当聪明的人认为没有特别强烈的理由使用不同的术语的迹象。

"

17
方法是一种特殊类型的函数,它有一个隐含参数传递(即定义该方法的类的实例)。这很重要,因为在严格意义上,函数不应使用或修改其参数列表之外的任何内容。 - ty1824
8
并非所有方法都会传递隐式参数。在Python中,self参数是显式的。许多语言具有静态方法,这些方法不会传递实例。 - Max Heiber
1
@mheiber 这些都是一些有价值的观点。关于 self,你是正确的,它是明确地 定义 的。关键在于调用是隐式的,基于原始对象引用。有些语言支持覆盖 thisself,但这些结构通常被称为函数,而不是方法。 - ty1824
1
就静态方法而言,Java 实现了它们作为一种解决方案,以便可以在不需要上下文的情况下实现函数。我甚至会提出“静态方法”是一个误导性的术语,应该在理想的理论世界中被替换掉... - ty1824
2
@ty1824 C++、Scala、Python、Ruby、JavaScript和Scala都有静态方法,所以我认为这不仅仅是Java的事情。我也不喜欢它们:它们相当于将对象(状态的捆绑)用作命名空间。 - Max Heiber
显示剩余5条评论

129

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

以下是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类,那么在这个类中只有一个叫bark的函数才有意义,这就是一个方法。如果你还有一个Person类,那么编写一个feed函数可能更有意义,因为人和狗都可以被喂养,且该函数不属于任何特定的类别,因此可以称之为函数。

4
这个答案——尤其是它的第一句话——迄今为止是对这个问题最简明扼要、整体最好的回答。 - yourcomputergenius
1
应该是 'def knock_door():' 吗? - Tom J
1
@TomJ 你说得对。也许是在社区编辑过程中丢失了?无论如何,还是谢谢。 - Gustavo Rubio

114

记忆方法:

  • Function(函数)→ Free(自由的)(自由意味着它可以放置在任何地方,不需要在对象或类中)
  • Method(方法)→ Member(成员)(对象或类的成员)

由于它们通常是可以互换的,为什么你需要助记符? - Sapphire_Brick
2
@Sapphire_Brick 我假设这是在它们不能互换的情况下。 - TylerH

55

FunctionMethod的主要区别可以通过以下非常通俗易懂的定义简单解释:

Function是在类外定义的,而Method是在类内定义并作为类的一部分。

请注意,原文中的html标签已经被保留。

38

面向对象编程的理念在于将软件视为由“对象”组成。现实世界中的对象具有属性。例如,如果您有一个员工对象,那么该员工具有姓名、员工ID、职位、所属部门等属性。

对象也知道如何处理其属性并对其执行一些操作。比方说,如果我们想知道一个员工正在做什么,我们会问他。

employe whatAreYouDoing.

“whatAreYouDoing”是发送给对象的“消息”。对象知道如何回答这个问题,可以说它有一个“方法”来解决这个问题。

因此,对象展示其行为的方式被称为方法。方法是对象必须执行某些操作的工具。

其他可能的方法包括:

employee whatIsYourName
employee whatIsYourDepartmentsName

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

// 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)没有涵盖面向对象编程范式,所以它们只称这些工件为“函数”。

例如,在C中,上述函数将是:

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

说一个对象有一个“功能”去执行某个动作并不是很“自然”,因为功能更多地与数学相关,而 Employee 并没有太多的数学内容,但你可以有方法来做完全相同的事情,例如在 Java 中这将是等效的 addValues 方法。

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

看起来很熟悉吧?这是因为Java有其源于C++和C,它们在实现上可能看起来相同,但在面向对象的文档中它们被称为方法。

这里是之前在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采用“自然语言”比喻的思想,这一点类似于某些面向对象编程语言(例如Smalltalk)。希望您在阅读本文后更容易理解面向对象中的方法。

注意:代码只是作为示例,无需编译。欢迎修改本文并添加Python示例。


22
在面向对象的世界中,两个术语通常被用来指代同一个东西。
从数学和计算机科学的角度来看,当使用相同的参数调用函数时,函数总是返回相同的结果(f(x,y) = (x+y))。另一方面,方法通常与类的实例相关联。虽然现代大多数面向对象的编程语言不再使用“函数”这个术语,但许多静态方法相当类似于函数,因为它们通常没有状态(并非总是如此)。

20

假设一个函数是一段代码块(通常具有自己的作用域,有时也具有自己的闭包),它可能接收一些参数并且可能返回结果。

方法是由对象拥有的函数(在某些面向对象系统中,更正确的说法是由类拥有)。被对象/类“拥有”意味着您通过对象/类引用该方法;例如,在Java中,如果您想调用对象“door”拥有的方法“open()”,则需要编写“door.open()”。

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

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


1
自从Javascript(你在问题中提到的语言)拥有方法属于对象而不是类(尽管存在类似于类的结构),违背了面向对象语言的一般趋势,我就一直强调方法可以由对象或类拥有。 - Mike Tunnicliffe

18

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接