Skip to content

Latest commit

 

History

History
104 lines (73 loc) · 3.54 KB

8、方法.md

File metadata and controls

104 lines (73 loc) · 3.54 KB

方法

  • 方法所属的类型并不一定是结构体类型,必须是某个自定义的数据类型,但不能是任何接口类型或接口的指针类型。

给一个函数类型 FuncJob 定义一个方法 func (f *FuncJob) Run()

type FuncJob func()

func (f *FuncJob) Run() {
   fmt.Println("job exe ....")
}
  • 一个数据类型关联的所有方法,共同组成了该类型的方法集合。

  • 同一个方法集合中的方法不能出现重名。

  • 结构体类型的方法:

    • 结构体类型的方法名称与结构体中任何字段的名称(包括成员变量名称)都不能重复。

方法屏蔽

  • 结构体嵌入的时候,会出现方法屏蔽现象:

    • 结构体 Dog 嵌入了结构体 Animal, 结构体 Animal 嵌入了结构体 Object
      • Dog 实现了与 Animal 相同名字的方法 Eat (只要方法名一样,不管方法签名),Dog 直接调用 Eat 方法是调用的 Dog 的,AnimalEat 方法被屏蔽了。
    • 结构体 Cat 嵌入了结构体 Animal, 结构体 Animal 嵌入了结构体 Object
      • Dog 可以直接调用 AnimalEat 方法。
    • DogEat 都可以通过链式的点语法(.)来调用 AnimalEat 方法。 (eg: d.Animal.Eat()c.Animal.Eat())
  • 多级嵌入方法屏蔽也是一样的,里层的会被外层的屏蔽掉。

  • 成员变量名和方法名相同,成员变量名和成员变量名,也会被屏蔽掉。

  • Go 通过嵌入字段的方式实现了类型之间的组合。(组合是非声明式的,不需要显示的声明某个类型实现了某个接口,不需要一个类型继承了另一个类型)

  • 通过嵌入字段实现:把一个类型的属性和操作给另一个类型,被嵌入类型也就实现了嵌入字段所实现的接口。

type Object struct {
}

type Animal struct {
	Object
}
func (p *Animal) Eat() {
	fmt.Println("animal eat")
}

type Dog struct {
	Animal
}
func (p *Dog) Eat() {
	fmt.Println("dog eat")
}

type Cat struct {
	Animal
}

func main() {
	//Animal 的方法 Eat,被 Dog 的 Eat 方法屏蔽了,或者直接使用点方法调用 Animal 的方法 Eat
	d := &Dog{}
	d.Eat()
	d.Animal.Eat()

	//Cat 可以直接调用嵌入类型 Animal 的方法 Eat,或者直接使用点方法调用 Animal 的方法 Eat
	c := &Cat{}
	c.Eat()
	c.Animal.Eat()
}

指针方法和值方法

方法 func (p *Dog) Eat() 就是一个指针方法。方法接收者是指针类型。

方法 func (p Dog) Run() 就是一个值方法。方法接收者是值类型(非指针类型)(可能是引用类型切片、字典等)。

func (p *Dog) Eat() {
	fmt.Println("dog eat")
}
func (p Dog) Run() {
	fmt.Println("dog eat")
}
  • 对接收者修改:

    • 值方法的接收者是值的一个副本(该接收者非引用类型),在方法内部修改接收者不会修改原值。
    • 指针方法接收者是指针的一个副本,方法内部修改的是副本指针指向的值,会修改原值。
  • 调用:

    • 指针类型的方法集合包括了所有的指针方法和所有的值方法。一个自定义数据类型的方法集合(即值方法集合)中只包含所有值方法。
    • 指针变量不仅可以调用指针方法,也可以调用值方法
    • 值变量不仅可以调用值方法,也可以调用指针方法 。(Go语言会自动使用该值变量的指针调用指针方法)
  • 基本类型和它的指针类型的方法集合是不同的,它们具体实现的接口类型的数量也不一定相同。