• Golang的封装继承与多态


    类的封装及方法绑定

    • Golang支持类的操作,但是没有class关键字,使用struct类模拟类
    • 在struct中定义函数需要在外部绑定,通过在方法前面指定数据类型类绑定方法到指定类,有点类似于C#的扩展函数
    package main
    
    import "fmt"
    
    // C++ 创建类的方式
    /*
    	class Person{
    		public:
    			string name
    			int age
    
    		public:
    			Sayhi(){
    				...
    			}
    	}
    */
    
    // Golang创建一个person类,绑定Sayhi()方法
    type Person struct {
    	Name string
    	Age int
    }
    
    // 在类外面绑定方法
    // 通过在方法前面指定数据类型类绑定方法到指定类,有点类似于C#的扩展函数
    // 下面这个Person数据类型,是Person对象的一个拷贝,在该函数下修改person里面的成员值,原始数据类型值不会改变
    // 如果想在绑定的函数中可以修改原始数据类型的值,可以通过指针func (person *Person) Sayhi(){}的方式来定义
    func (person Person) Sayhi(){
    	// 类的方法,使用自己的成员Name
    	fmt.Println("hi, my name is ",person.Name)
    }
    
    // 通过指针的方式将函数绑定在指定类中,在该函数下可以修改原始数据类型的成员值
    func (this *Person) SayHello(){
    	this.Name = "china"
    	fmt.Println("hi, my name is ",this.Name)
    }
    
    func main() {
    	person := Person{
    		Name: "simple",
    		Age: 25,
    	}
    	fmt.Println(person)
    	person.Sayhi()
    
    	fmt.Println(person)
    	person.SayHello()
    }
    
    

    image

    类的继承

    • 当我们在一个类中,直接包含另外一个类的类型,并且没写字段名的时候。它默认就是对另一个类的继承
    • 继承的时候,虽然没有定义字段名称,但是会自动创建一个默认的同名字段,这是为了在子类中,依然可以操作父类,因为子类父类可能出现同名的字段
    package main
    
    import "fmt"
    
    // 定义一个人类
    type Human struct {
    	Name   string
    	Age    int
    	Gender int
    }
    
    // 给人类绑定一个打招呼的方法
    func (this *Human) Sayhi() {
    	fmt.Println("hello, my name is ", this.Name, "age is ", this.Age)
    }
    
    // 定义一个学生
    // 在其他类中引用指定类
    type Student struct {
    	hum    Human		// 类的嵌套
    	School string
    }
    
    // 定义一个老师,来继承Human
    type Teacher struct {
    	Human					// 当我们在一个类中,直接包含另外一个类的类型,并且没写字段名的时候。它默认就是对另一个类的继承
    	Subject string
    
    }
    
    func main() {
    	// 在学习类的继承之前,我们先来看一下类的嵌套
    	strudent := Student{hum: Human{
    		Name:   "Simple",
    		Age:    24,
    		Gender: 1,
    	},
    		School: "成都七中",
    	}
    	fmt.Println(strudent)
    
    	// 继承类
    	teacher := Teacher{}
    	teacher.Name = "陈老师"
    	teacher.Age = 30
    	teacher.Subject = "计算机"
    	fmt.Println(teacher)
    	teacher.Sayhi()				// 同时绑定的方法也继承下来了
    
    	// 继承的时候,虽然没有定义字段名称,但是会自动创建一个默认的同名字段
    	// 这是为了在子类中,依然可以操作父类,因为子类父类可能出现同名的字段
    	teacher.Human.Name = "林老师"
    	fmt.Println(teacher)
    	teacher.Sayhi()				// 同时绑定的方法也继承下来了
    }
    
    

    image

    类的访问权限(访问修饰符)

    • 在Golang中,权限都是通过首字母大小写来标识的
    • import -> 如果包名不同,只有大写字母开头的才能访问
    • 对于类里面的成员、方法 -> 只有首字母大写才能在其他包中使用

    多态(通过interface实现)

    接口的使用

    • 在C++中,实现接口的时候,使用纯虚函数代替接口
    • 在Golang中,有专门的关键字interface来代表接口
    • interface不仅仅是用于处理多态的,它可以接收任意的数据类型,类似于void
    package main
    
    import "fmt"
    
    // 在C++中,实现接口的时候,使用纯虚函数代替接口
    // 在Golang中,有专门的关键字interface来代表接口
    // interface不仅仅是用于处理多态的,它可以接收任意的数据类型,类似于void
    func main() {
    	var i, j, k interface{}
    	names := []string{"simple", "china"}
    
    	i = names
    	fmt.Println("i代表切片数组:", i)
    
    	age := 24
    	j = age
    	fmt.Println("j代表数字:", j)
    
    	str := "hello world"
    	k = str
    	fmt.Println("k代表字符串:", k)
    
    	// 上上面的代码中,我们现在只知道k是interface,但是不能够明确知道它代表的数据类型
    	// 通过变量.(数据类型)判断指定interface是否为指定的数据类型
    	kval, ok := k.(int)
    	if !ok {
    		fmt.Println("k不是int")
    	} else {
    		fmt.Println("k是int,值为:", kval)
    	}
    
    	// 最常用的常见:把interface当初函数的参数,类似于fmt.Println函数,func Println(a ...interface{}) (n int, err error) {}
    	// 可以通过switch来判断用户输入的数据类型,然后根据不同的数据类型做相应的逻辑处理
    
    	// 创建一个具有三个接口的数据切片
    	array := make([]interface{}, 4)
    	array[0] = 1
    	array[1] = "hello world"
    	array[2] = true
    	array[3] = 3.1415
    
    	for _, val := range array{
    		// 获取当前接口的真正数据类型
    		switch t := val.(type) {
    		case int:
    			fmt.Printf("当前数据类型为int,内容为:%d
    ",t)
    		case string:
    			fmt.Printf("当前数据类型为string,内容为:%s
    ",t)
    		case bool:
    			fmt.Printf("当前数据类型为bool,内容为:%v
    ",t)				// %v可以自动推导数据类型
    		default:
    			fmt.Printf("不是合理的数据类型")
    		}
    	}
    }
    
    

    image

    多态

    • C语言的多态需要父子继承关系
    • Golang的多态不需要继承,只要实现了相同的接口即可
    • 实现Golang多态,需要定义接口
    package main
    
    import "fmt"
    
    // 定义一个飞的行为,不同可以飞行的东西可能不一样
    
    // 定义一个接口,注意类型是interface
    type IFly interface {
    	// 接口函数可以有多个,但是只能有原型,不能有实现
    	Fly()
    }
    
    // 定义一个老鹰类
    type Glede struct {
    	Name string
    }
    
    // 老鹰的飞行函数
    func (this *Glede) Fly() {
    	fmt.Println(this.Name, ":展翅翱翔")
    }
    
    type Human struct {
    	Name string
    }
    
    func (this *Human) Fly() {
    	fmt.Println(this.Name,":不会飞")
    }
    
    // 实现多态:定义一个多态的通用接口,传入不同的对象,调用通向的方法,实现不同的效果
    func DoFly(fly IFly)  {
    	fly.Fly()
    }
    
    func main() {
    	glede := Glede{Name: "老鹰"}
    	glede.Fly()
    
    	var fly IFly				// 定义一个包含Fly的接口变量
    	fly = &glede				// 对fly赋值为glede,接口需要使用指针来赋值
    	fly.Fly()
    
    	human := Human{Name: "人类"}
    	human.Fly()
    
    	fly = &human
    	fly.Fly()
    
    	// 多态的实现
    	fmt.Println("***多态***")
    	DoFly(&glede)
    	DoFly(&human)
    }
    

    image

    • 定义一个接口,里面设计好需要的接口,可以有多个
    • 任何实现了这个接口的类型,都可以赋值给这个接口,从而实现多态
    • 多个类之间不需要有继承关系
    • 如果interface定义了多个接口,那么实现类必须实现全部函数,才可以赋值
  • 相关阅读:
    内联元素和块元素
    inline-block
    overflow:hidden
    鼠标点到某个位置出现手势的效果。
    对于清浮动问题,终极。
    将所需要的图标排成一列组成一张图片,方便管理。li的妙用
    异步错误处理 -- 时机
    错误传播 --try{}catch(e){console.log(e)}
    js
    jquery源码学习-2-选择器
  • 原文地址:https://www.cnblogs.com/insipid/p/15345101.html
Copyright © 2020-2023  润新知