如何理解go中的函数与方法

如何理解这句话
方法是与对象实例绑定的特殊函数。
方法是面向对象编程的基本概念,用于维护和展示对象的自身状态。对象是内敛的,每
个实例都有各自不同的独立特征,以属性和方法来暴露对外通信接口。普通函数则专注
于算法流程,通过接收参数来完成特定逻辑运算,并返回最终结果。换句话说,方法是
有关联状态的,而函数通常没有。
方法和函数定义语法区别的在于前者有前置实例接收参数(receiver),编译器以此确定
方法所属类型。在某些语言里,尽管没有显式定义,但会在调用时隐式传递s实例参数。

这段话从概念和语法两个层面对比了方法(method)函数(function),并将其放在面向对象编程(OOP)的背景下进行解释。让我逐步拆解并帮你理解这句话的含义。


1. “方法是与对象实例绑定的特殊函数”

含义

  • 方法:方法是一种特殊的函数,它与某个对象(实例)关联在一起。换句话说,方法是“属于”某个对象的。
  • 对象实例:在 OOP 中,对象是类的实例化结果,每个对象都有自己的状态(属性)和行为(方法)。
  • 绑定:方法通常需要操作对象的状态,因此它与对象绑定在一起,调用时会作用于特定的实例。

示例(Go 语言)

type Person struct {
    Name string
}

func (p Person) Say() string { // 方法,绑定到 Person 类型
    return "Hello, " + p.Name
}

func main() {
    p := Person{Name: "Tom"}
    fmt.Println(p.Say()) // 调用方法,输出 "Hello, Tom"
}
  • SayPerson 类型的方法,与实例 p 绑定,访问 p.Name

对比普通函数

func say(name string) string { // 普通函数
    return "Hello, " + name
}
  • say 是一个独立函数,不绑定任何对象,纯粹通过参数 name 操作。

2. “方法是面向对象编程的基本概念,用于维护和展示对象的自身状态”

含义

  • 基本概念:在 OOP 中,方法是对象行为的核心表达方式。
  • 维护和展示状态:方法的主要作用是操作对象的内部数据(属性),或者向外界展示对象的状态。
  • 例子:一个 Person 对象可能有 Name 属性,方法 Say 可以展示这个状态,方法 SetName 可以修改它。

示例

func (p *Person) SetName(name string) { // 修改状态
    p.Name = name
}
  • SetName 方法维护了 p 的状态(Name 属性)。

3. “对象是内敛的,每个实例都有各自不同的独立特征,以属性和方法来暴露对外通信接口”

含义

  • 内敛的:对象的状态(属性)通常是私有或受控的,不会随意暴露。
  • 独立特征:每个对象实例都有自己的属性值,例如两个 Person 实例可以有不同的 Name
  • 对外通信接口:对象通过属性(有时直接访问)和方法与外界交互,方法是主要的交互方式。

示例

p1 := Person{Name: "Tom"}
p2 := Person{Name: "Alice"}
fmt.Println(p1.Say()) // "Hello, Tom"
fmt.Println(p2.Say()) // "Hello, Alice"
  • p1p2 是独立的实例,各自有不同的 Name,通过 Say 方法展示。

4. “普通函数则专注于算法流程,通过接收参数来完成特定逻辑运算,并返回最终结果”

含义

  • 普通函数:不像方法那样与对象绑定,函数更关注独立的任务或算法。
  • 参数和返回:函数通过输入参数执行逻辑,输出结果,不依赖任何对象的状态。

示例

func add(a, b int) int { // 普通函数
    return a + b
}
  • add 只关心输入 ab,计算并返回结果,没有状态关联。

5. “换句话说,方法是有关联状态的,而函数通常没有”

含义

  • 方法的状态关联:方法通常操作对象的属性(状态),依赖于实例的上下文。
  • 函数的无状态性:函数不绑定对象,通常是“纯函数”,只依赖输入,不涉及外部状态。

对比

  • 方法:p.Say() 依赖 p.Name,有状态。
  • 函数:say("Tom") 不依赖任何对象状态,只依赖参数。

6. “方法和函数定义语法区别的在于前者有前置实例接收参数 (receiver),编译器以此确定方法所属类型”

含义

  • 接收者(receiver):在 Go 中,方法定义时有一个显式的接收者参数,指定方法绑定到的类型。
  • 语法区别
    • 函数:func name(params) returnType
    • 方法:func (receiver Type) name(params) returnType
  • 编译器作用:接收者告诉编译器这个方法属于哪个类型。

示例(Go)

func (p Person) Say() string { // 方法,接收者是 p,类型是 Person
    return "Hello, " + p.Name
}

func say(name string) string { // 函数,无接收者
    return "Hello, " + name
}
  • p 是接收者,Say 属于 Person 类型。

7. “在某些语言里,尽管没有显式定义,但会在调用时隐式传递实例参数”

含义

  • 隐式传递:在一些语言(如 Python、JavaScript)中,方法调用时会隐式传递实例(通常称为 selfthis),不需要显式声明接收者。
  • 与 Go 的区别:Go 要求显式定义接收者,而其他语言可能在底层自动处理。

示例(Python)

class Person:
    def __init__(self, name):
        self.name = name
    
    def say(self): # 隐式传递 self
        return "Hello, " + self.name

p = Person("Tom")
print(p.say()) # 输出 "Hello, Tom"
  • self 是隐式传递的,等价于 Go 的显式接收者 p

Go 的显式性

  • Go 中必须写 (p Person),强制显式绑定,体现了 Go 的简单和透明哲学。

如何整体理解这句话?

核心思想

  • 方法 vs 函数
    • 方法是面向对象的一部分,与对象实例绑定,关注状态的管理和行为。
    • 函数是独立的,关注算法和逻辑,无状态关联。
  • OOP 中的方法
    • 方法是对象与外界交互的接口,依赖于对象的属性。
    • 每个实例有独立状态,方法操作这些状态。
  • 语法的体现
    • 方法通过接收者(receiver)绑定类型,Go 显式定义,其他语言可能隐式传递。

用类比理解

  • 方法:就像某个人的“说话”能力,依赖于这个人的名字(状态),每个人说的话不同。
  • 函数:就像一个计算器,只管输入数字,算出结果,不关心是谁在用它。

Go 的视角

  • Go 的方法设计体现了其“轻量面向对象”哲学:通过接收者绑定方法,通过接口实现多态,但避免了传统 OOP 的复杂继承体系。

总结

  • 概念上:方法是有状态的,函数是无状态的;方法服务于对象,函数服务于逻辑。
  • 语法上:方法有接收者(显式或隐式),函数没有。
  • 实践中:在 Go 中,方法通过 (receiver Type) 绑定对象,其他语言可能隐式处理(如 Python 的 self)。

如果你对某个部分还有疑问,或者想深入某一点(比如 Go 的接收者 vs Python 的 self),随时告诉我!

posted @ 2025-03-04 13:48  仁义礼智信的  阅读(21)  评论(0)    收藏  举报