Go 语言程序设计——面向对象编程(2)

添加方法

  • 方法是作用在自定义类型的值上的一类特殊函数,通常自定义类型的值会被传递给该函数
  • 方法可以以指针或者值的形式传递,这取决于方法如何定义
  • 定义方法的语法几乎等同于定义函数
  • 可以为任何自定义类型添加一个或者多个方法
  • 一个方法的接收者总是一个该类型的值,或者只是该类型的指针
  • 对于任何一个给定的类型,每个方法名必须唯一
  • Go 语言推荐的方式是使用名字唯一的函数
  • 例子:
type Count int

func (count *Count) Increment() { *count++ }
func (count *Count) Decrement() { *count-- }
func (count Count) IsZero() bool { return count == 0 }

var count Count
i := int(count)
count.Increment()
j := int(count)
count.Decrement()
k := int(count)
fmt.Println(count, i, j, k, count.IsZero())
  • 类型的方法集是指可以被该类型的值调用的所有方法的集合
  • 数据类型的值很大,或者需要修改该值,则需要让方法接受一个指针类型的接收者

重写方法

  • 任何嵌入类型中的方法都可以当做该自定义结构体自身的方法被调用,并且可以将其内置类型作为其接收者
  • 例子:
type Item struct {
  id string // 具名字段(聚合)
  price float64 // 具名字段(聚合)
  quantity int // 具名字段(聚合)
}

func (item *Item) Cost() float64 {
  return item.price * float64(item.quantity)
}

type SpecialItem struct {
  Item  // 匿名字段(嵌入)
  catalogId int // 具名字段(聚合)
}

// SpecialItem嵌入了一个Item类型。这意味着我们可以在一个SpecialItem上调用Item的Cost()方法

special := SpecialItem{Item{"Green", 3, 5}, 207}
fmt.Println(special.id, special.price, special.quantity, special.catalogId)
fmt.Println(special.Cost())
  • 当调用 special.Cost() 的时候,由于 SpecialItem 类型没有它自身的 Cost() 方法, Go 语言会使用 Item.Cost() 方法
  • 也可以在自定义的结构体中创建与所嵌入的字段中的方法同名的方法,来覆盖被嵌入字段中的方法:
type LuxuryItem struct {
  Item                  // 匿名字段(嵌入)
  markup float64 // 具名字段(聚合)
}

func (item *LuxuryItem) Cost() float64 { // 没必要这么冗长
  return item.Item.price * float64(item.Item.quantity) * item.markup
}

func (item * LuxuryItem) Cost() float64 { // 没必要的重复!
  return item.price * float64(item.quantity) * item.markup
}

func (item * LuxuryItem) Cost() float64 { // 完美
  return item.Item.Cost() * item.markup
}

推荐阅读更多精彩内容