go 3.37 面向对象

  1. 同名字段和结构体匿名字段
  2. 结构体指针类型匿名字段
  3. 面向过程与面向对象的区别
  4. 方法表达式
  5. 接口定义和实现
  6. 多态的表现
  7. 接口继承

同名字段和结构体匿名字段

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
package main

import "fmt"

type person struct {
name string
sex byte
age int
}

type student struct {
person //只有类型,没有变量名,是匿名字段,继承了person的成员
id int
name string
addr string
}

func main() {
var s student //声明一个变量
// 就近原则:如果在本作用域中找到此成员,就操作此成员,如果没有找到,找到继承的字段
s.name = "mike" //student name 属于同名字段,就近原则操作本作用域字段
s.sex = 'm' //person sex 就近原则,本作用域没有找到,操作person的字段
s.age = 18 //person age 就近原则,本作用域没有找到,操作person的字段
s.addr = "bj" //student add 就近原则,本作用域找到,操作student字段
s.person.name = "jack" //person name 显式操作person字段
fmt.Printf("s = %+v\n", s)
}

结构体指针类型匿名字段

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
package main

import "fmt"

type person struct {
name string
sex byte
age int
}

type student struct {
*person //指针类型
id int
addr string
}

func main() {
//直接使用取地址初始化指针类型
s1 := student{&person{"mike", 'm', 18}, 666, "bj"}
fmt.Println(s1.name, s1.sex, s1.age, s1.id, s1.addr)
//方法二:先定义变量
var s student
s.person = new(person) // 分配空间
s.name = "yoyo"
s.sex = 'f'
s.age = 19
s.addr = "sz"
fmt.Println(s.name, s.sex, s.age, s.id, s.addr)
}

面向过程与面向对象的区别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 面向过程,实现2个数相加
func Add01(a, b int) int {
return a + b
}

type v int // 面向对象,方法:给某个类型绑定一个函数
// 面向对象,把两个象相加
// tmp为接收者,another为形参名,代表另一个对象,最后一个v代表反回值(对象)类型,
func (tmp v) Add02(another v) v {
return tmp + another
}

func main() {
var result int
a := 10
b := 20
result = Add01(a, b)
fmt.Println("result = ", result)

var obj v = 10
r := obj.Add02(100)
fmt.Println("obj result = ", r)
}

方法表达式

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
package main

import "fmt"

type person struct {
name string
sex byte
age int
}

func (p person) setInfoValue() {
fmt.Printf("setInfoValue:%p ,%v\n", &p, p)
}

func (p *person) setInfoPointer() {
fmt.Printf("setInfoPointer:%p ,%v\n", p, p)
}

func main() {
p := person{"mike", 'm', 18}
f1 := p.setInfoPointer //方法值
f1() // 隐藏接收者

f2 := (person).setInfoValue // 方法表达式
f2(p) //显示把接受者传递进去

f3 := (*person).setInfoPointer
f3(&p) //显示把接受者传递进去

}

接口定义和实现

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
type Human interface {
// 方法,只有声明,没有实现,由别的类型(自定义类型)实现
sayhi()
}

type Student struct {
name string
id int
}

// Student实现了此方法
func (tmp *Student) sayhi() {
fmt.Printf("Student [%s,%d] sayhi\n", tmp.name, tmp.id)
}

type Teacher struct {
addr string
group string
}

// Teacher实现了此方法
func (tmp *Teacher) sayhi() {
fmt.Printf("Teacher [%s,%s] sayhi\n", tmp.addr, tmp.group)
}

type MyStr string

// Mystr实现了此方法
func (tmp *MyStr) sayhi() {
fmt.Printf("MyStr [%s] sayhi\n", *tmp)
}

func main() {
// 定义接口类型的变量
var i Human
s := Student{"mike", 666}
i = &s // 只要是实现了此接口方法的类型,那么这个类型的变量(接收者类型)就可以给接口实例赋值
i.sayhi()

t := &Teacher{"bj","go"}
i = t
i.sayhi()

var str MyStr = "HELLO STR"
i = &str
i.sayhi()
}

多态的表现

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
package main

import "fmt"

func whoSayHi(i Human) {
i.sayhi()
}

type Human interface {
// 方法,只有声明,没有实现,由别的类型(自定义类型)实现
sayhi()
}

type Student struct {
name string
id int
}

// Student实现了此方法
func (tmp *Student) sayhi() {
fmt.Printf("Student [%s,%d] sayhi\n", tmp.name, tmp.id)
}

type Teacher struct {
addr string
group string
}

// Teacher实现了此方法
func (tmp *Teacher) sayhi() {
fmt.Printf("Teacher [%s,%s] sayhi\n", tmp.addr, tmp.group)
}

type MyStr string

// Mystr实现了此方法
func (tmp *MyStr) sayhi() {
fmt.Printf("MyStr [%s] sayhi\n", *tmp)
}

func main() {
s := &Student{"mike", 666}
t := &Teacher{"bj", "go"}
var str MyStr = "HELLO STR"
//调用同一个函数,不同的表现,多态(polymorphic),多种形态
whoSayHi(s)
whoSayHi(t)
whoSayHi(&str)

// 创建一个切片
x := make([]Human, 3)
x[0] = s
x[0] = t
x[0] = &str
//第一个返回下标,第二个返回下标所对应的值
for _, i := range x {
i.sayhi()
}
}

接口继承

4.22

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
type Human interface {
// 方法,只有声明,没有实现,由别的类型(自定义类型)实现
sayhi()
}

type Person interface {
//Human // 匿名字段,继承了sayhi()
sing(lrc string)
}
type Student struct {
name string
id int
}

// Student实现了sayhi方法
func (tmp *Student) sayhi() {
fmt.Printf("Student [%s,%d] sayhi\n", tmp.name, tmp.id)
}

// Student实现了sing方法
func (tmp *Student) sing(lrc string) {
fmt.Printf("Student [%s,%d] sing %s\n", tmp.name, tmp.id, lrc)
}

func main() {
var i Person

s := &Student{"mike", 666} // Student实现了sayhi方法,那么s就可以给接口实例i赋值
i = s
i.sayhi() // 继承来的方法
i.sing("学生歌...")
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 rootid@126.com

文章标题:go 3.37 面向对象

本文作者:Shawn

发布时间:2019-05-31, 19:04:26

最后更新:2019-07-30, 17:24:30

原始链接:https://gitrootid.github.io/2019/05/31/golang/go-4-02-面向对象_/

版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。

目录
×

喜欢就点赞,疼爱就打赏