• Go面向对象


    特点

    1. 面向对象的三个特性:封装、继承、多态。go 不支持继。
    2. 实例和实例的指针都可以访问封装的数据属性(普通字段)和函数属性(方法)。
    3. struct 对应 python 中的 class
    4. 接口类型是一种抽象的类型,就是在普通类型(出接口类型外的其它类型)的基础上再抽象,然后暴漏出它们共有的方法(顺带也就把它们归类了)

    封装

    package struct_lean
    
    import (
    	"fmt"
    	"testing"
    	"unsafe"
    )
    
    type Employee struct {
    	Id   string
    	Name string
    	Age  int
    }
    
    func TestCreateEmployeeObj(t *testing.T)  {
    	e := Employee{"0", "Bob", 15}
    	e1 := Employee{Name:"Tom", Age:30}
    	e2 := new(Employee) // 返回指针
    	e2.Id = "2"
    	e2.Name = "Jake"
    	e2.Age = 16
    	t.Log(e)
    	t.Log(e1)
    	t.Log(e2)
    	t.Log(e2.Age)
    }
    
    // 方式一:这种方式在实例对应方法被调用时,实例的成员会进行复制
    //func (e Employee) String() string {
    //	fmt.Printf("Address is %x
    ", unsafe.Pointer(&e.Name))
    //	return fmt.Sprintf("ID:%s-Name:%s-Age:%d", e.Id, e.Name, e.Age)
    //}
    
    // 方式二:使用这种方式可以避免内存拷贝
    func (e *Employee) String() string {
    	fmt.Printf("Address is %x
    ", unsafe.Pointer(&e.Name))
    	return fmt.Sprintf("ID:%s-Name:%s-Age:%d", e.Id, e.Name, e.Age)
    }
    
    func TestStructOperations(t *testing.T)  {
    	e := Employee{"0", "Bob", 20}
    	fmt.Printf("Address is %x
    ", unsafe.Pointer(&e.Name))
    	t.Log(e.String())
    }
    

    运行上面的TestStructOperations,我们可以通过判断打印的两个ID值是否相等来判断是否发生内存拷贝

    不支持继承,支持组合

    可以实现方法重载,但是不能实现子类替换父类,不能实现真正的继承

    package inherit_test
    
    import (
    	"fmt"
    	"testing"
    )
    
    // Pet 相当于基类
    type Pet struct {
    }
    
    func (p *Pet) Speak() {
    	fmt.Print("...")
    }
    
    func (p *Pet) SpeakTo(host string) {
    	p.Speak()
    	fmt.Print(" ", host)
    }
    
    // Dog 相当于子类
    type Dog struct {
    	*Pet
    }
    
    // 把父类的方法重写
    func (d *Dog) Speak() {
    	fmt.Print("Wang!")
    }
    
    func TestDog(t *testing.T) {
    	dog := new(Dog)
    	dog.SpeakTo("MaYun")
    }
    

    运行上面测试程序打印"... MaYun"并不是"Wang! MaYun",子类的 Speak 没有执行;
    Pet 和 Dog 是完全不同的两种类型,我们没有办法把进行相互转换(实现不了LSP),所以 go 不支持继承。
    这其实就是个组合

    接口

    package interface_test
    
    import "testing"
    
    type Programmer interface {
    	WriteHelloWorld() string
    }
    
    type GoProgrammer struct {
    }
    
    func (g *GoProgrammer) WriteHelloWorld() string {
    	return "fmt.Println("Hello World")"
    }
    
    func TestClient(t *testing.T) {
    	var p Programmer
        // p 声明为 Programmer 类型,但是赋值为 *GoProgrammer 也不会 panic, 这就是接口的用途
        // p = &GoProgrammer{}
    	p = new(GoProgrammer) // 必须用指针去调用接口的成员
    	t.Log(p.WriteHelloWorld())
    }
    

    多态

    通过接口的方式支持多态

    package polym_test
    
    import (
    	"fmt"
    	"testing"
    )
    
    type Code string
    
    type Programmer interface {
    	WriteHelloWorld() Code
    }
    
    type Goprogrammer struct {
    }
    
    func (g *Goprogrammer) WriteHelloWorld() Code {
    	return "fmt.Println("Hello World!")"
    }
    
    type JavaProgrammer struct {
    }
    
    func (j JavaProgrammer) WriteHelloWorld() Code {
    	return "System.out.Println("Hello World!")"
    }
    
    func writeFirstProgram(p Programmer)  {
    	fmt.Printf("%T %v
    ", p, p.WriteHelloWorld())
    }
    
    // 多态测试
    func TestPolymorphism(t *testing.T)  {
    	goProg := new(Goprogrammer) // interface 只能对应指针实例
    	javaProg := new(JavaProgrammer)
    	writeFirstProgram(goProg)
    	writeFirstProgram(javaProg)
    }
    
  • 相关阅读:
    VS缓冲区溢出,未对变量进行检查
    Mutex与Event控制互斥事件的使用详解
    error LNK2019: 无法解析的外部符号
    [转] 兼容IE和Firefox的设为首页和收藏的Javascript代码
    [转]超时时间以到,但尚未从池中获取连接
    Datalist的嵌套使用
    由服务器端向客户端输出脚本
    几个国外的XHTML模板站,DIV+CSS模板下载(转)
    gridview隐藏某一列
    [转]简单谈基于SQL SERVER 分页存储过程的演进
  • 原文地址:https://www.cnblogs.com/wuyongqiang/p/12120446.html
Copyright © 2020-2023  润新知