函数与方法:一个容易被忽视的编程概念差异 lxx 2025年10月30日 目次 从学习C语言接触计算机开始,我总以为函数和方法不过是两个不同的名称而已,只不过是习惯不同。直到阅读Rust语言的文档时,同时出现了"方法"和"函数"两个术语,我才意识到这其中的差异。
事实上,它们不能说是两个完全不同的概念,但确实存在区别。
什么是方法(Method) # 在面向对象编程中,方法 (英语:Method;德语:Methode;法语:Méthode)指的是属于类别(所谓的类方法、静态方法或工厂方法)或者对象(所谓的实例方法)的子程序。如同过程化程序设计的程序,一个方法通常由一系列语句组成,并以此完成一个动作。它可以通过输入一组参数来指定所需的动作,且部分方法可能会有输出值(所谓的返回值)。方法的目的是提供一个机制,以访问(读取和写入)对象或类别的私有数据 。
参考:Wikipedia - Method (computer programming)
函数与方法的区别 # Wikipedia关于函数的条目中有这样一段描述:
Some programming languages, such as COBOL and BASIC, make a distinction between functions that return a value (typically called “functions”) and those that do not (typically called “subprogram”, “subroutine”, or “procedure”); some, such as C, C++, and Rust, only use the term “function” irrespective of whether they return a value or not; others, such as ALGOL 60 and PL/I, only use the word procedure. Some object-oriented languages, such as Java and C#, refer to functions inside classes as “methods”.
参考:Wikipedia - Function (computer programming)
如果你去搜索相关讨论,会发现基本能形成的共识是:定义在类内部的称为Method(方法),定义在类外部的称为Function(函数) 。
各语言中的实践 # 理解了这个理论后,我们再来看各种语言的实现就清晰多了。
Java # Java中所有的"函数"都必须定义在类中,无论是成员方法还是静态方法,因此统一称为方法 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class Calculator {
private int offset = 0 ;
// 实例方法
public int add ( int a , int b ) {
return a + b + offset ;
}
// 静态方法
public static int multiply ( int a , int b ) {
return a * b ;
}
}
// 使用
Calculator calc = new Calculator ();
calc . add ( 1 , 2 ); // 调用实例方法
Calculator . multiply ( 3 , 4 ); // 调用静态方法
Kotlin # Kotlin既可以像Java一样在类内部定义,这些被称为方法 ;也可以定义在类的外部,因此扩展函数被称为"扩展函数 ",而不是"扩展方法"。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 顶层函数
fun add ( a : Int , b : Int ): Int {
return a + b
}
class Calculator ( private var offset : Int = 0 ) {
// 成员方法
fun add ( a : Int , b : Int ): Int {
return a + b + offset
}
}
// 扩展函数(注意是"函数"不是"方法")
fun Calculator . subtract ( a : Int , b : Int ): Int {
return a - b
}
C++ # C++同时支持函数和方法,但在术语上都统称为"function"。
函数(Function) :定义在类外部的独立函数
1
2
3
4
5
6
7
8
9
10
11
// 全局函数
int add ( int a , int b ) {
return a + b ;
}
// 命名空间中的函数
namespace Math {
int multiply ( int a , int b ) {
return a * b ;
}
}
方法(Method) :定义在类内部的成员函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Calculator {
public :
// 实例方法(成员函数)
int add ( int a , int b ) {
return a + b + offset ;
}
// 静态方法
static int multiply ( int a , int b ) {
return a * b ;
}
private :
int offset = 0 ;
};
// 使用
Calculator calc ;
calc . add ( 1 , 2 ); // 调用实例方法
Calculator :: multiply ( 3 , 4 ); // 调用静态方法
Go # Go语言明确区分函数和方法的概念。
函数(Function) :独立定义的函数
1
2
3
4
5
6
7
8
// 包级别函数
func Add ( a , b int ) int {
return a + b
}
func main () {
result := Add ( 1 , 2 )
}
方法(Method) :绑定到特定类型的函数(通过接收者receiver定义)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
type Calculator struct {
offset int
}
// 值接收者方法
func ( c Calculator ) Add ( a , b int ) int {
return a + b + c . offset
}
// 指针接收者方法
func ( c * Calculator ) SetOffset ( offset int ) {
c . offset = offset
}
// 使用
calc := Calculator { offset : 10 }
calc . Add ( 1 , 2 ) // 调用方法
calc . SetOffset ( 20 ) // 调用方法
Rust # Rust也明确区分函数和方法,这也是最初让我意识到这个差异的语言。
函数(Function) :独立定义的自由函数
1
2
3
4
5
6
7
8
9
10
11
// 自由函数(free function)
fn add ( a : i32 , b : i32 ) -> i32 {
a + b
}
// 模块中的函数
mod math {
pub fn multiply ( a : i32 , b : i32 ) -> i32 {
a * b
}
}
方法(Method) :在impl块中为类型定义的函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
struct Calculator {
offset : i32 ,
}
impl Calculator {
// 关联函数(Associated Function) - 类似静态方法,没有self参数
fn new ( offset : i32 ) -> Self {
Calculator { offset }
}
// 实例方法 - 带有self参数
fn add ( & self , a : i32 , b : i32 ) -> i32 {
a + b + self . offset
}
// 可变引用方法
fn set_offset ( & mut self , offset : i32 ) {
self . offset = offset ;
}
}
// 使用
let mut calc = Calculator ::new ( 10 ); // 调用关联函数
calc . add ( 1 , 2 ); // 调用实例方法
calc . set_offset ( 20 ); // 调用可变方法
总结 # 语言 函数(Function) 方法(Method) 特点 Java 不存在 所有都是方法 必须定义在类中 Kotlin 顶层函数、扩展函数 类成员方法 同时支持两者 C++ 全局函数、命名空间函数 类成员函数 术语上都称为function Go 包级别函数 带接收者的函数 明确区分,方法必须有receiver Rust 自由函数、模块函数 impl块中的函数 明确区分,有self的是方法,无self的是关联函数
核心区别其实很简单:方法(Method)与类型/对象绑定,函数(Function)独立存在。
上篇:命名的艺术:从驼峰到蛇形
下篇:Android依赖管理解析:从ext到 Version Catalog的演进