Go语言面向对象编程——结构化 方法 继承

7

Go语言面向对象编程——结构化 方法 继承

author: histonevon@zohomail.com

date: 2020/08/04

  • go语言支持类似于C语言中的面向对象的风格

1.结构体(类)定义

定义格式如下:

 type 类型名 struct {
     字段1 字段1类型
     字段2 字段2类型
     …
 }
  • 类型名:标识自定义结构体的名称,在同一个包内不能重复

  • 字段1、字段2 ……:表示结构体字段名,结构体中的字段名必须唯一

  • 字段1类型、字段2类型……:表示结构体各个字段的类型

 //定义一个点类,坐标x y均为float64类型
 type Point struct {
     x float64
     y float64
 }

同类型变量可以写在同一行

以下语句同上面的语句等价

 //定义一个点类,坐标x y均为float64类型
 type Point struct {
     x,y float64
 }
  • 可见性规则

    • 成员或方法首字母大写 public

    • 成员或方法首字母小写 private

 // object project main.go
 package main
 ​
 import (
     "fmt"
 )
 ​
 //对象
 type Point struct {
     x float64
     y float64
 }
 ​
 func main() {
     var p *Point = new(Point)
     //通过内置函数new来建立对象,new返回一个指针,指向一块内存单元,其所占存储槽初始化为零。
     p.x = 3 //p虽然是指针,但用取成员运算符即可,不需指向运算符
     p.y = 4
 ​
     q := new(Point) //这样也可
     q.x = 5
     q.y = 6
 ​
     r := Point{7, 8}              //直接初始化,value
     var s Point = Point{9, 10}    //完整直接初始化,value
     var t *Point = &Point{11, 12} //完整直接初始化,pointer
     u := &Point{13, 14}           //简写,pointer
     fmt.Println(p)
     fmt.Println(q)
     fmt.Println(r)
     fmt.Println(s)
     fmt.Println(t)
     fmt.Println(u)
 }
 ​

object1

2.方法

  • 声明了类,就可以将该类型显示的作为第一个参数来定义方法

  • eg.坐标变换器

 // object project main.go
 package main
 ​
 import (
     "fmt"
     "math"
 )
 ​
 //对象
 type Point struct {
     x float64
     y float64
 }
 ​
 func (self Point) Distance() float64 { //self为自身对象,实际上是函数的参数
     return math.Sqrt(self.x*self.x + self.y*self.y)
 }
 ​
 func (self *Point) Scale(factor float64) { //坐标放大器
     self.x *= factor
     self.y *= factor
 }
 ​
 func main() {
     p1 := Point{3, 4}
     fmt.Println(p1.Distance())
     p1.Scale(2) //坐标放大2
     fmt.Println(p1)
 }
 ​

object2

  • 在函数名前定义接收器,表示该方法作用的目标,也是方法的第一个参数

  • 接收器类型和参数类型类似,可以是指针类型和非指针类型

  • 方法名、参数列表、返回参数:格式与函数定义一致

  • 官方建议使用接收器类型名的第一个小写字母,也可自己定义

 //接收器变量为 Point型
 func (self Point) Distance() float64 { //self为自身对象,实际上是函数的参数
     return math.Sqrt(self.x*self.x + self.y*self.y)
 }
 ​
 //接收器变量为 Point型指针
 func (self *Point) Scale(factor float64) { //坐标放大器
     self.x *= factor
     self.y *= factor
 }
  • 注意 在计算机中,小对象由于值复制时的速度较快,所以适合使用非指针接收器,大对象因为复制性能较低,适合使用指针接收器,在接收器和参数间传递时不进行复制,只是传递指针。

3.继承

 // object project main.go
 package main
 ​
 import (
     "fmt"
     // "math"
 )
 ​
 //继承
 //定义user类
 type user struct {
     name string
     age  byte
 }
 ​
 //定义方法
 func (u user) Output() string {
     return fmt.Sprintf("%+v", u) //Sprintf表示格式化输出为字符串
 }
 ​
 //定义leader类
 type leader struct {
     user  //匿名成员,实现继承
     title string
 }
 ​
 func main() {
     var l leader
     l.name = "Tim" //继承user.name
     l.age = 19     //继承user.age
     l.title = "sales manager"
     fmt.Println(l.Output()) //继承user.Output()
 ​
     //匿名成员有和类型一样的名字,所以可以这样
     l.user.name = "Tom"          //未继承user.name
     l.user.age = 20              //未继承user.age
     fmt.Println(l.user.Output()) //未继承user.Output()
 }
 ​

object3

  • go通过匿名组合来实现类似继承的功能,在子类中匿名声明父类即可

  • 子类继承后可以通过 "." 直接访问父类成员,如:l.name = "Tim"

  • 也可以不进行继承,通过访问匿名成员来访问父类成员,如:l.user.name = "Tom"

  • Sprintf表示格式化输出为字符串

4.总结

面向对象只是换了一种语法方式表达而已