Bootstrap

Go语言基础(二)封装继承多态、方法、接口

封装

go语言中可以简单地看作对struct的封装

type Person struct {
    name string
}
type Student struct {
    name string
}
type Teacher struct {
    name string
}

继承

go语言中没有继承,但可以通过“匿名组合”实现继承
结构体继承,方法继承,方法重写

//父类
type Person struct {
    name string
    age int
}
type Student struct {
    Person //匿名继承
    //*Person //指针作为匿名字段
    //p Person//别名继承
    height string
    //子类和父类字段重名
    name string 
    
}
type Teacher struct {
    Person //匿名继承
    //*Person //指针作为匿名字段
    //p Person//别名继承
    sex string
}

//基本类型不能作为对象直接使用,为基本类型绑定方法,需要起别名才可以
type newint int
func (i newint) add(a newint) newint {
	return a + 1
}

//方法继承和重写(给结构体绑定方法)
//*代表是否可以读写(修改),*代表接收者为指针
func (p *Person) eat(){
	fmt.Println("人类吃饭")

}
func (p *Person) drink(){
	fmt.Println("人类喝水")

}
func (p *Student) eat(){
	fmt.Println("学生吃饭")
}


func main() {
	tea :=Teacher{Person{"人类",1},"男"}
    //子类和父类字段重名,默认给子类赋值,给父类赋值需要加父类名称调用
	tea.name = "张飞"
	tea.Person.name = "大飞"
	//子类可以直接使用父类字段
	fmt.Println(tea.name)
	fmt.Println(tea.age)
	fmt.Println(tea.sex)

	stu :=Student{Person{"人类",1},"188"}
	//方法继承,子类可以直接调用父类方法
	stu.drink()
	//方法重写,默认执行子类方法
	stu.eat()
	stu.Person1.eat()

	
	//如果是指针作为匿名字段
	var stu Student
	//需要new一个空间
	stu.Person = new(Person)
	//正常模式
	(*stu.Person).name = "典韦"
	//简易模式
	stu.name = "诸葛亮"
	fmt.Println(stu.name)

	//使用别名调用方法
	var newi newint
	result :=newi.add(2)
	fmt.Println("为int定义别名",result)
}

多态(接口作为参数实现多态)

接口

接口 ,给结构体定义接口,那么必须定义接口里面的所有方法才可以


//定义接口
type IHuman interface {
	say()
	eat()
}
type Stus struct {
	name string
	age  int
}

type Teas struct {
	name string
	age  int
	sex  string
}

//结构体实现接口方法1
func (stus *Stus) eat() {
	fmt.Println(stus.name, "正在吃饭")
}
//结构体实现接口方法2
func (stus *Stus) say() {
	fmt.Println(stus.name, "正在说话")
}

func (tea *Teas) eat() {
	fmt.Println(tea.name, "正在吃饭")
}
func (tea *Teas) say() {
	fmt.Println(tea.name, "正在说话")
}

//将接口作为函数参数实现多态
func dotest(hu IHuman) {
	hu.say()
	hu.eat()

}
//测试
func main() {
//多态调用
	stus := Stus{"诸葛", 1}
	dotest(&stus)
	tea := Teas{"老师", 1,"男"}
	dotest(&tea)

	var h IHuman
	h = &stus
	h.say()
	h.eat()
}


接口继承和转换

//接口继承和转换
type Humans interface {//子集
	eat()
}

type Persons interface {//超集
	Humans //匿名继承接口
	say()
}

type Students struct {
	name string
	age int
}

func (stus *Students)say()  {
	fmt.Println(stus.name,"在说话")
}
func (stus *Students)eat()  {
	fmt.Println(stus.name,"在吃东西")
}

func main() {
	var h Humans
	stu :=Students{"飞飞",1}
	h = &stu
	h.eat()

	var p Persons
	p = &stu
	p.eat()
	p.say()

	//超集中包含所有子集的方法
	//超集合赋值给子集,子集不能赋值给超集
	h = p
	//p = h   //这样是不可以的
	h.eat()

}

空接口和类型断言

//空接口
var i interface{}
//空接口类型的切片
var ni []interface{}

func test() {
	fmt.Println("函数调用")
}

func main() {
	//空接口可以接受任意类型数据
	i = 10
	fmt.Printf("%T\n", i)
	fmt.Println(i)
	i = "你好"
	fmt.Println(i)
	fmt.Printf("%T\n", i)

	//接口切片可以放任意类型
	app := append(ni, 88, "飞飞", 3.23, test)

	//里面的值不能直接使用,要通过类型断言才可以
	for a := 0; a < len(app); a++ {
		fmt.Println(app[a])
	}

	for _, v := range app {
		if value, ok := v.(int); ok {
			fmt.Println("int数据", value)
		} else if test, ok := v.(func()); ok {
			test()
		} else if value, ok := v.(string); ok {
			fmt.Println("sting数据", value)
		}
	}

	//类型断言
	//值,值的判断bool = 接口变量(数据类型)
	value, ok := i.(string)
	if ok {
		fmt.Println("结果正确", value)
	} else {
		fmt.Println("错误")
	}

}

异常

//异常处理
func adder(a int, b int) (value int, err error) {
	if b == 0 {
		err = errors.New("除数不能为0")
		return
	}
	value = a / b
	return
}
//延迟调用defer
func prin() {
	defer fmt.Println("温馨提示1")
	fmt.Println("温馨提示2")
	fmt.Println("温馨提示3")
}
;