GO 学习笔记——第四天 / 面向对象_多态

1.匿名组合

package main

import "fmt"

//自定义类型
type XX string

type Person struct {
name string
sex bool
age int
}

type Student struct {
//匿名字段
Person
id int
address string
//同名函数
name string
//基础匿名字段
XX
//指针类型
eat *string
}

func main() {

//初始化
s := Student{Person{"LGL", true, 20}, 001, "JX", "Tom", "XX", &"eat"}
fmt.Println(s)
//输出 {{LGL true 20} 1 JX Tom}
//成员操作
fmt.Println(s.name)
//输出 Tom

//同名函数 就近原则
s.name = "Test"
fmt.Println(s)
//输出 {{LGL true 20} 1 JX Test}
s.Person.name = "XXX"
fmt.Println(s)
//输出 {{XXX true 20} 1 JX Test}
}

2.方法

  • 要注意方法和函数是不一样的
  • 面向对象和面向过程的方法区别
package main

import "fmt"

//实现两数相加

//1.面向过程
func Add1(a, b int) int {
return a + b
}

//2.面向对象
type MyNum int

//tmp:接收者,接收者就是传递的一个参数
func (tmp MyNum) Add2(other MyNum) MyNum {
return tmp + other
}

func main() {
fmt.Println(Add1(1, 2))

var a MyNum = 2
fmt.Println(a.Add2(3))
}
  • 结构体类型添加方法
  • 接收的类型不同,同名也没关系,类似重载
package main

import "fmt"

type Student struct {
name string
sex bool
age int
}

func (tmp Student) Print() {
fmt.Println(tmp)
}

//通过成员函数 给成员赋值
func (p *Student) Op(name string, sex bool, age int) {
p.name = name
p.sex = sex
p.age = age
}

func main() {
s := Student{"LGL", true, 18}
s.Print()
//输出 {LGL true 18}

var p Student
(&p).Op("ZS", false, 19)
p.Print()
//输出 {ZS false 19}
}
  • 这里也要注意一下引用传递和值传递的方法,和之前一样
package main

import "fmt"

type Student struct {
name string
sex bool
age int
}

func (temp Student) PrintInfo() {
fmt.Println(temp)
}

//值传递与引用传递

//接收者为普通变量 非指针 值语义 一份拷贝
func (temp Student) setInfoValues(n string, s bool, a int) {
temp.name = n
temp.sex = s
temp.age = a

fmt.Println("setInfoValues = ", temp)
//setInfoValues = {B false 21}
}

//接收者为指针变量 引用传递
func (temp *Student) setInfoPointer(n string, s bool, a int) {
temp.name = n
temp.sex = s
temp.age = a
fmt.Println("setInfoPointer = ", temp)
//setInfoPointer = &{C true 22}
}

func main() {
s1 := Student{"A", true, 20}
fmt.Println("1 = ", s1)
//1 = {A true 20}

s1.setInfoValues("B", false, 21)
fmt.Println("2 = ", s1)
//2 = {A true 20}

s1.setInfoPointer("C", true, 22)
fmt.Println("3 = ", s1)
//3 = {C true 22}
}
  • 方法集
package main

import "fmt"

type Student struct {
name string
sex bool
age int
}

func (temp Student) SetInfoValues() {
fmt.Println("SetInfoValues")
}

func (temp *Student) SetInfoPointer() {
fmt.Println("SetInfoPointer")
}

func main() {
//结构体变量是一个指针变量,它能够调用哪些方法,这些方法就是一个集合,简称方法集
p := &Student{"Tom", false, 12}
p.SetInfoPointer()
//内部做了转换,先把指针p 转成*p后再调用
p.SetInfoValues()
}
  • 方法继承
package main

import "fmt"

type Person struct {
name string
sex bool
age int
}

//人类输出
func (temp *Person) PrintInfo() {
fmt.Println(temp)
}

//学生 继承 人类
type Student struct {
Person
id int
address string
}

func main() {
p := Student{Person{"A", true, 20}, 001, "jx"}
p.PrintInfo()
//&{A true 20}

//方法也同样继承
}
  • 方法重写
package main

import "fmt"

type Person struct {
name string
sex bool
age int
}

//人类输出
func (temp *Person) PrintInfo() {
fmt.Println(temp)
}

//学生 继承 人类
type Student struct {
Person
id int
address string
}

//学生输出
func (temp *Student) PrintInfo() {
fmt.Println(temp)
}

func main() {
p := Student{Person{"A", true, 20}, 001, "jx"}
p.PrintInfo()
//&{{A true 20} 1 jx}
p.Person.PrintInfo()
//&{A true 20}

//就近原则输出
}
  • 方法值:给方法调用赋值一个变量 p := Person.Println()
  • 方法表达式: 给方法名赋值一个变量 p:= Person.Println p(xxx)

3.接口

GO 学习笔记——第四天 / 面向对象_string类_02

  • 接口的命名通常会以er结尾
  • 多态的表现
package main

import "fmt"

type Personer interface {
Eat()
}

type Student struct {
name string
id int
}

func (temp *Student) Eat() {
fmt.Println("Eat", temp)
}

type TT struct {
name string
id int
}

func (temp *TT) Eat() {
fmt.Println("TT", temp)
}

//多态
func Who(p Personer) {
p.Eat()
}

func main() {

//var p Personer
s := &Student{"LGL", 1}
t := &TT{"TT", 1}
//p = s
//p.Eat()

//只要初始类型继承此接口就可以多态
Who(s)
//Eat &{LGL 1}
Who(t)
//TT &{TT 1}

//创建一个切片
x := make([]Personer, 2)
x[0] = s
x[1] = t

for _, i := range x {
fmt.Println("i:", i)
}
}
  • 接的继承口
package main

import "fmt"

type Iner1 interface {
Eat()
}

type Iner2 interface {
Iner1
Sleep()
}

//定义一个学生
type Student struct {
name string
id int
}

//实现吃的接口
func (temp *Student) Eat() {
fmt.Println("Eat")
}

//实现睡觉的接口
func (temp *Student) Sleep() {
fmt.Println("Sleep")
}

func main() {
var i Iner2
s := &Student{"LGL", 0}
i = s
i.Eat()
i.Sleep()
}
  • 接口转换
package main

import "fmt"

//子集
type Iner1 interface {
Eat()
}

//超集
type Iner2 interface {
Iner1
Sleep()
}

//定义一个学生
type Student struct {
name string
id int
}

//实现吃的接口
func (temp *Student) Eat() {
fmt.Println("Eat")
}

//实现睡觉的接口
func (temp *Student) Sleep() {
fmt.Println("Sleep")
}

func main() {
//接口转换 超集 ——> 子集 反之不允许
var i1 Iner1
var i2 Iner2
//OK
i1 = i2
//NO
i2 = i1

fmt.Println(i1)
fmt.Println(i2)
}
  • 空接口
func main() {
//空接口为万能类型
var i interface{} = 1
fmt.Println(i)

i = "Hello World"
fmt.Println(i)
}
  • 类型查询
  • 断言
package main

import "fmt"

type Student struct {
name string
id int
}

func main() {

i := make([]interface{}, 3)

i[0] = 1
i[1] = "H"
i[2] = Student{"lgl", 123}

//查询类型 类型断言
for index, data := range i {
//第一个返回的是值 第二个是真假
if value, ok := data.(int); ok == true {
fmt.Println("index = ", index, "为int类型,值为:", value)
//index = 0 为int类型,值为: 1
} else if value, ok := data.(string); ok == true {
fmt.Println("index = ", index, "为string类型,值为:", value)
//index = 1 为string类型,值为: H
} else if value, ok := data.(Student); ok == true {
fmt.Println("index = ", index, "为Student类型,值为:", value)
//index = 2 为Student类型,值为: {lgl 123}
}
}
}
- switch
//查询类型 类型断言
for index, data := range i {

switch value := data.(type) {
case int:
fmt.Println("index = ", index, "为int类型,值为:", value)
case string:
fmt.Println("index = ", index, "为string类型,值为:", value)
case Student:
fmt.Println("index = ", index, "为Student类型,值为:", value)
}
}