36、Go 结构体 - 面向对象之方法集
hi,我是温新
什么是方法集
在go语言中,每个类型都有与之关联的方法,把这个类型的所有方法称为类型的方法集。
来看个简单的案例:
package main
import "fmt"
func main() {
s2 := &Students{"王小丽", 18}
s2.showName()
}
type Students struct {
name string
age int8
}
func (s Students) showName() {
fmt.Println(s.name)
}
func (s *Students) setName(name string) {
s.name = name
}
类型 Students 方法集包含了 ShowName 方法;
类型 *Students 方法集包含了 ShowName 和 SetName 方法。为什么会是这样,来看看方法集的规则,如下:
类型 | 方法参数接收类型 |
---|---|
T | (t T) |
*T | (t T) and (t *T) |
这个规则是什么意思呢?如下:
- 类型 T 方法集包含全部 receiver T 方法;
- 类型 *T 方法集包含全部 receiver T + *T 方法;
- 若类型 S 包含匿名字段 T,则 S 和 *S 方法集包含 T 方法;
- 若类型 S 包含匿名字段 *T,则 S 和 *S 方法集包含 T + *T 方法;
- 不管是嵌套 T 还是 *T, *S 方法集总是包含 T + *T 方法。
用实例 value 和 pointer 调用方法 (含匿名字段) 不受方法集约束,编译器总是查找全部方法,并自动转换 receiver 实参。
方法集案例
类型 T 方法集包含全部 receiver T 方法
package main
import "fmt"
func main() {
t1 := T{1}
fmt.Printf("t1 is : %v\n", t1)
t1.test()
}
type T struct {
int
}
func (t T) test() {
fmt.Println("类型 T 方法集包含全部 receiver T 方法。")
}
输出结果:
t1 is : {1}
类型 T 方法集包含全部 receiver T 方法。
类型 *T
方法集包含全部 receiver T + *T
方法
package main
import "fmt"
func main() {
t1 := Ty{1}
// 指针赋值
t2 := &t1
fmt.Printf("t2 是:%v\n", t2)
t2.testT()
t2.testP()
}
type Ty struct {
int
}
func (t Ty) testT() {
fmt.Println("类型 *Ty 方法集包含全部 receiver Ty 方法。")
}
func (t *Ty) testP() {
fmt.Println("类型 *Ty 方法集包含全部 receiver *Ty 方法。")
}
输出结果
t2 是:&{1}
类型 *Ty 方法集包含全部 receiver Ty 方法。
类型 *Ty 方法集包含全部 receiver *Ty 方法。
若类型 S 包含匿名字段 T,则 S 和 *S 方法集包含 T 方法
package main
import "fmt"
func main() {
s1 := S{T1{1}}
s2 := &s1
fmt.Printf("s1 是 %v\n", s1)
s1.testT()
fmt.Printf("s2 是 %v\n", s2)
s2.testT()
}
type T1 struct {
int
}
type S struct {
T1
}
func (t T1) testT() {
fmt.Println("如类型 S 包含匿名字段 T1,则 S 和 *S 方法集包含 T1 方法。")
}
输出结果:
s1 是 {{1}}
如类型 S 包含匿名字段 T1,则 S 和 *S 方法集包含 T1 方法。
s2 是 &{{1}}
如类型 S 包含匿名字段 T1,则 S 和 *S 方法集包含 T1 方法。
这条规则说的是当我们嵌入一个类型,嵌入类型的接受者为值类型的方法将被提升,可以被外部类型的值和指针调用。
若类型 S 包含匿名字段 *T,则 S 和 *S 方法集包含 T + *T 方法
package main
import "fmt"
func main() {
s1 := S1{T2{1}}
s2 := &s1
fmt.Printf("s1 is : %v\n", s1)
s1.testT()
s1.testP()
fmt.Printf("s2 is : %v\n", s2)
s2.testT()
s2.testP()
}
type T2 struct {
int
}
type S1 struct {
T2
}
func (t T2) testT() {
fmt.Println("如类型 S1 包含匿名字段 *T2,则 S1 和 *S1 方法集包含 T2 方法")
}
func (t *T2) testP() {
fmt.Println("如类型 S1 包含匿名字段 *T,则 S1 和 *S1 方法集包含 *T2 方法")
}
输出结果如下:
s1 is : {{1}}
如类型 S1 包含匿名字段 *T2,则 S1 和 *S1 方法集包含 T2 方法
如类型 S1 包含匿名字段 *T,则 S1 和 *S1 方法集包含 *T2 方法
s2 is : &{{1}}
如类型 S1 包含匿名字段 *T2,则 S1 和 *S1 方法集包含 T2 方法
如类型 S1 包含匿名字段 *T,则 S1 和 *S1 方法集包含 *T2 方法
这条规则说的是当我们嵌入一个类型的指针,嵌入类型的接受者为值类型或指针类型的方法将被提升,可以被外部类型的值或者指针调用。
请登录后再评论