//继承
type Person struct {
id int
name string
age int
}
/**
通过匿名字段实现了继承,将公共的属性封装在Person中,在Student中直接包含Person,那么Student中就有了Person中所有的成员,Person就是匿名字段。
*/
type Student struct {
Person
score float32
}
func main() {
//顺序初始化
s1 := Student{Person{1, "张三", 28}, 97}
fmt.Println(s1) //{{1 张三 28} 97}
//s1.Person.name 和 s1.name是一样的效果。如果在Student中也加入了一个成员name,这样与Person中的name重名了。
//基本的原则:如果能够在自己对象所属的类(结构体)中找到对应的成员,那么直接进行操作,如果找不到就去对应的父类(结构体)中查找。这就是所谓的就近原则。
fmt.Println(s1.id) //1
fmt.Println(s1.name) //张三
fmt.Println(s1.age) //28
fmt.Println(s1.score) //97
//指定初始化成员
s2 := Student{Person: Person{name: "李四"}, score: 88}
fmt.Println(s2) //{{0 李四 0} 88}
//成员操作
s2.Person.id = 2
s2.Person.age = 22
fmt.Println(s2) //{{2 李四 22} 88}
s2.Person = Person{3, "王五", 26}
fmt.Println(s2) //{{3 王五 26} 88}
}
1.1 指针类型匿名字段
type Person struct {
id int
name string
age int
}
type Student struct {
*Person
score float32
}
func main() {
s1 := Student{&Person{1, "张三", 28}, 97}
fmt.Println(s1) //{0xc04204a3a0 97}
fmt.Println(s1.id, s1.name, s1.age, s1.score) //1 张三 28 97
fmt.Println(s1.Person.id, s1.Person.name, s1.Person.age, s1.score) //1 张三 28 97
var s2 Student
s2.Person = new(Person)
s2.id = 2
s2.name = "李四"
s2.age = 22
s2.score = 88
fmt.Println(s2.id, s2.name, s2.age, s2.score) //2 李四 22 88
}
2.方法
方法,大家可以理解成就是函数,但是在定义使用方面与前面讲解的函数还是有区别的。
GO中没有方法重载(所谓重载,指的是方法名称一致,参数类型,个数不一致)。
type Integer int //给int类型指定了一个别名叫Integer,别名可以随便起,只要符合GO语言的命名规则就可以。
//定义了一个方法,方法的定义与函数的区别
func (a Integer) Sum(b Integer) Integer {
return a + b
}
func main() {
var num Integer = 2
result := num.Sum(3)
fmt.Println(result) //5
}
2.1 给结构体添加方法
接收者为普通变量,非指针,是值传递
接收者为指针变量,引用传递
type Person struct {
id int
name string
}
type Student struct {
Person
score float32
}
/*
如果给结构体(类)加上了方法,那么根据结构体(类)创建完成对象后,是不是就可以通过对象加上“点”,就可以完成方法的调用。
这与调用类中定义的属性的方式是完全一样的。这样就完成了通过方法与属性来描述一个对象的操作。
*/
func (s Student) ShowInfo() {
fmt.Println(s.id, s.name, s.score)
}
//要修改其对应的值,将方法的接收者,修改成对应的指针类型。
func (s *Student) ModifyInfo(id int, name string, score float32) {
s.id = id
s.name = name
s.score = score
}
func main() {
s1 := Student{Person{1, "张三"}, 97}
s1.ShowInfo() //1 张三 97
(&s1).ModifyInfo(2, "李四", 88)
fmt.Println(s1.id, s1.name, s1.score) //2 李四 88
}
type Person struct {
id int
name string
}
func (p *Person) ModifyInfo(id int, name string) {
p.id = id
p.name = name
}
type Student struct {
Person
score float32
}
func main() {
s := Student{Person{1, "张三"}, 97}
s.ModifyInfo(1, "李四")
fmt.Println(s.id, s.name, s.score) //1 李四 97
}
4.方法重写
GO中没有方法重载(所谓重载,指的是方法名称一致,参数类型,个数不一致)。
type Person struct {
id int
name string
}
func (p *Person) ModifyInfo(id int, name string) {
p.id = id
p.name = name
}
type Student struct {
Person
score float32
}
func (s *Student) ModifyInfo(id int, name string) {
s.id = id
s.name = "学生:"+name
}
func main() {
s := Student{Person{1, "张三"}, 97}
s.ModifyInfo(1, "李四")
fmt.Println(s.id, s.name, s.score) //1 学生:李四 97
}
5.接口
type Humaner interface {
SayHi()
}
type Student struct {
id int
name string
}
func (s *Student) SayHi() {
fmt.Println(s.id, s.name)
}
type Teacher struct {
name string
sex string
}
func (t *Teacher) SayHi() {
fmt.Println(t.name, t.sex)
}
func main() {
var i Humaner
s := &Student{1, "张三"}
t := &Teacher{"张老师", "男"}
//只要类(结构体)实现对应的接口,那么根据该类创建的对象,可以赋值给对应的接口类型。
i = s
i.SayHi() //1 张三
i = t
i.SayHi() //张老师 男
}
6.多态
type Humaner interface {
SayHi()
}
type Student struct {
id int
name string
}
func (s *Student) SayHi() {
fmt.Println(s.id, s.name)
}
type Teacher struct {
name string
sex string
}
func (t *Teacher) SayHi() {
fmt.Println(t.name, t.sex)
}
func WhoSayHi(i Humaner) {
i.SayHi()
}
func main() {
s := &Student{1, "张三"}
t := &Teacher{"张老师", "男"}
WhoSayHi(s) //1 张三
WhoSayHi(t) //张老师 男
}
6.1多态案例
实现一个计算器功能案例
package main
import "fmt"
//定义操作父类
type Operation struct {
numA float32
numB float32
}
//定义接口
type Getresulter interface {
GetResult() float32 //计算器:方法有返回值
}
//继承:加法
type OperationAdd struct {
Operation
}
//计算器:加法实现接口
func (a *OperationAdd) GetResult() float32 {
return a.numA + a.numB
}
//继承:减法
type OperationSub struct {
Operation
}
//计算器:减法实现接口
func (a *OperationSub) GetResult() float32 {
return a.numA - a.numB
}
//创建一个工厂类
type OperationFactory struct {
}
//工厂类添加方法
func (f *OperationFactory) CreateOption(option string, numA float32, numB float32) float32 {
var result float32
switch option {
case "+":
add := &OperationAdd{Operation{numA, numB}}
result = OperationWho(add)
case "-":
sub := &OperationSub{Operation{numA, numB}}
result = OperationWho(sub)
}
return result
}
//多态调用计算器方法
func OperationWho(i Getresulter) float32 {
return i.GetResult()
}
func main() {
var opfactory OperationFactory
add := opfactory.CreateOption("+", 10, 20) //加法
fmt.Println(add) //30
sub := opfactory.CreateOption("-", 10, 20) //减法
fmt.Println(sub) //-10
}
func main() {
//空接口万能类型,保存任意类型的值
var i interface{} = 1
fmt.Println(i) //1
i = "abc"
fmt.Println(i) //abc
}
7.1类型断言
func main() {
arrs := make([]interface{}, 3)
arrs[0] = 123
arrs[1] = 3.14
arrs[2] = "hello"
for _, v := range arrs {
//对数据v进行类型断言
if data, ok := v.(int); ok {
fmt.Println(data)
} else if data, ok := v.(float64); ok {
fmt.Println(data)
} else if data, ok := v.(string); ok {
fmt.Println(data)
}
}
}