Go面向对象相关知识

类的封装和绑定方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package main

import "fmt"

// go语言没有class关键字生成类
// 使用struct声明类

type Person struct {
   // 成员属性
   name   string
   age    int
   gender string
}

// 类外边绑定方法
// 类的方法,可以使用自己的成员
// 使用指针可以修改类的成员变量等

func (p *Person) Eat() {
   fmt.Println("使用 *Person 指针 修改前")
   fmt.Println(p.name + " is eating")
   p.name = "luenci"
   fmt.Println("使用 *Person 指针 修改后")
   fmt.Println(p.name + " is eating")
}

func (p Person) Eat2() {
   fmt.Println("使用 Person 不是指针 修改前")
   fmt.Println(p.name + " is eating")
   p.name = "luenci"
   fmt.Println("使用 Person 不是指针 修改后")
   fmt.Println(p.name + " is eating")
}

func main() {
   lynn := Person{
      name:   "lynn",
      age:    20,
      gender: "girl",
   }

   lynn.Eat()
   lynn.Eat2()

}

类的继承

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
package main

import "fmt"

type Human struct {
   name string
   sex  string
   age  int
}

type Student struct {
   hum    Human // 包含 Human类型的变量 是嵌套类
   school string
}

type Teacher struct {
   Human  // 直接声明Human类型,没有定义变量 类继承
   school string
}

// 类外面绑定方法

func (h *Human) Eat() {
   fmt.Println(h.name + " is eating")
}

func main() {
   st1 := Student{
      hum: Human{
         name: "lynn",
         sex:  "girl",
         age:  20,
      },
      school: "一中",
   }
   fmt.Println("st1", st1)
   fmt.Println("st1 name", st1.hum.name)

   t1 := Teacher{}
   t1.school = "一中"
   t1.name = "lynn"
   t1.sex = "girl"
   t1.age = 20

   fmt.Println("t1", t1)
   fmt.Println("t1 name", t1.name)
   // 继承的时候虽然我们没有声明变量名称,但是默认自动会给类型创建一个同名字段
   // 这是为了能在子类中操作父类,因为:子类父类可能出现同名字段
   fmt.Println("t1 age", t1.Human.age)
}

类成员访问权限(字段大小写)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package src

import "fmt"

// 类外面绑定方法
// 即使在类的定义前也没关系,go应该不是逐行运行

func (h *Human) Eat() {
   fmt.Println(h.Name + " is eating")
}

type Human struct {
   Name string
   Sex  string
   Age  int
}

type Student struct {
   Hum    Human // 包含 Human类型的变量 是嵌套类
   School string
}

type Teacher struct {
   Human  // 直接声明Human类型,没有定义变量 类继承
   School string
}
package main

import (
   "fmt"
   "luenci/github.com/day03/3.类成员访问权限/src"
)

// go语言中,权限都是通过首字母大小写来控制的
// import XX 如果package名称不同,那么只有大写字母开头的才是 Public
// 对于类里面的成员、函数等,只有大写字母开头的才能在其他的包中使用
// 如果在用一个package(文件下)下则无以上限制

func main() {
   st1 := src.Student{
      Hum: src.Human{
         Name: "lynn",
         Sex:  "girl",
         Age:  20,
      },
      School: "一中",
   }

   fmt.Println("st1", st1)
   fmt.Println("st1 name", st1.Hum.Name)

   t1 := src.Teacher{}
   t1.School = "一中"
   t1.Name = "lynn"
   t1.Sex = "girl"
   t1.Age = 20

   fmt.Println("t1", t1)
   fmt.Println("t1 name", t1.Name)
   fmt.Println("t1 age", t1.Human.Age)
}

接口

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package main

import (
   "fmt"
)

// go语言中,interface代表接口
// interface 不仅仅是用来处理多态,它可以接收任意的数据类型

func main() {
   // func Println(a ...interface{}) (n int, err error) { ... }

   // 定义三个接口类型
   var i, j, k interface{}

   i = []string{"lynn", "luenci"}
   j = 98
   k = false

   // 快速判断接口的类型
   //jType := reflect.TypeOf(j) 反射
   jType, ok := j.(int)
   fmt.Println("ok", ok)
   if !ok {
      fmt.Println("j不是int类型")
   }

   fmt.Println("jType", jType)
   fmt.Println(i, j, k)

   // 最常用的场景:把interface当成一个函数的参数,(类似于上面的 Println函数) ,使用switch来判断用户输入的不同类型
   // 根据不同类型,做相关的逻辑处理

   // 创建一个具有三个接口类型的切片
   array := make([]interface{}, 3)
   array[0] = 3
   array[1] = "luenci"
   array[2] = true

   for _, value := range array {
      // 获取接口中真正的数据类型
      switch v := value.(type) {
      case int:
         fmt.Println("当前数据类型为int,内容为:", v)
      case string:
         fmt.Println("当前数据类型为string,内容为:", v)
      case bool:
         fmt.Println("当前数据类型为bool,内容为:", v)
      default:
         fmt.Println("不是合理的数据类型")
      }
   }

}

多态

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package main

import "fmt"

// go语言多态,需要实现定义接口

// 定义一个接口,类型是interface
type IAttack interface {
   // 如果定义了多个接口函数,那么实现的类必须全部实现这些接口,才可以赋值
   Attack() // 接口函数可以有多个,但是只能有函数原型,不可以有实现
}

// 低等级玩家
type HumanLowLevel struct {
   name  string
   level int
}

func (a *HumanLowLevel) Attack() {
   fmt.Println("我是", a.name, "等级为", a.level, "造成伤害1000")
}

// 高等级玩家
type HumanHighLevel struct {
   name  string
   level int
}

func (a *HumanHighLevel) Attack() {
   fmt.Println("我是", a.name, "等级为", a.level, "造成伤害50000")
}

// 定义一个多态的通用接口,传入不同的对象,调用相同的函数,实现不同的效果
func DoAttack(a IAttack) {
   a.Attack()
}

func main() {
   //var player IAttack // 定义一个包含Attack的接口变量

   lowLevel1 := HumanLowLevel{
      name:  "luenci",
      level: 0,
   }

   HighLevel1 := HumanHighLevel{
      name:  "lynn",
      level: 1000,
   }

   // 两个不同对象调用相同方法
   DoAttack(&HighLevel1)
   DoAttack(&lowLevel1)

   //lowLevel1.Attack()

   // 对player赋值为lowLevel1,接口需要使用指针类型来赋值
   //player = &lowLevel1
   //player.Attack()
}