Study Golang — (5) 方法

1、方法声明

方法的声明与普通函数的声明类似,只是在函数名字前面多了一个参数,这个参数把这个方法绑定到这个参数对应的类型上。
例如:

参数p称为方法的接收者。
表达式p.Distance称为选择子(selector)

另一个例子:

在使用方法的时候主要注意几点:

  • 虽然方法的名字一模一样,但是如果接收者不一样,那么方法就不一样
  • 方法里面可以访问接收者的字段
  • 调用方法通过.访问,就像struct里面访问字段一样

在上例,method area() 分别属于Rectangle和Circle, 于是他们的 Receiver 就变成了Rectangle 和 Circle, 或者说,这个area()方法 是由 Rectangle/Circle 发出的。
值得说明的一点是,图示中method用虚线标出,意思是此处方法的Receiver是以值传递,而非引用传递,是的,Receiver还可以是指针, 两者的差别在于, 指针作为Receiver会对实例对象的内容发生操作,而普通类型作为Receiver仅仅是以副本作为操作对象,并不对原实例对象发生操作。后文对此会有详细论述。
那是不是method只能作用在struct上面呢?当然不是咯,他可以定义在任何你自定义的类型、内置类型、struct等各种类型上面。这里你是不是有点迷糊了,什么叫自定义类型,自定义类型不就是struct嘛,不是这样的哦,struct只是自定义类型里面一种比较特殊的类型而已,还有其他自定义类型申明,可以通过如下这样的申明来实现。

例如:

2、指针做为接收者

或:

或:

或:

也就是说:
如果一个方法的接收者是*T,你可以在一个T类型的实例变量V上面调用这个方法,而不需要&V去调用这个方法,编译器会隐式地获取变量的地址。
如果一个方法的接收者是T,你可以在一个*T类型的变量P上面调用这个方法,而不需要 *P去调用这个方法,编译器会隐式地解引用接收者,获取实际的取值。

实际上,编译器会对变量进行 &p的隐匿转换。
只有变量才允许这么做,包括结构体字段如p.X,数组或slice的元素如s[0]。
不可以对不能取地直Point接收者参数调用*Point的方法,因为无法获取临时变量的地址,如:
Point{1, 2}.ScaleBy(2) // 编译错误,不能获取Point类型字面量的地址

3、方法变量与方法表达式

方法变量是一个函数,把方法绑定到一个接收者p上。函数只需要提供实参而不需要提供接收者就能够调用。

如果包内的API调用一个函数值,并且使用者期望这个函数的行为是调用一个特定接收者的方法,那么方法变量就非常有用。

方法表达式写成 T.f 或者 (*T).f,其中T是类型,是一种函数变量,把原来方法的接收者替换成函数的第一个参数,因此它可以像平常的函数一样调用。

4、封装

要封装一个对象,必须使用结构体。
在Go语言中封装的单元是包,而不是类型。
无论是在函数内的代码还是方法内的代码,结构体类型内的字段对于同一个包中的所有代码都是可见的。

封装提供了三个优点:

  • 第一,因为使用方不能直接修改对象的变量,所以不需要更多的语句来检查变量的值。
  • 第二,隐藏实现细节可以防止使用方依赖的属性发生改变,使得设计者可以更加灵活地改变API的实现而不破坏兼容性。
  • 第三,可以防止使用者肆意改变对象内的变量。

————————————————————

原创文章,转载请注明: 转载自孙希栋的博客

本文链接地址: 《Study Golang — (5) 方法》

发表评论

电子邮件地址不会被公开。 必填项已用*标注

Scroll Up