zoukankan      html  css  js  c++  java
  • Go(三)面向对象

    封装数据和行为

    数据封装

    结构定义

    type Employee struct {
        Id string
        Name string
        Age int
    }

    field后面没有逗号

    实例创建及初始化

    e := Employee{"0", "Bob", 20}
    e1 := Employee{Name: "Mike", Age: 30}
    e2 := new(Employee) // 注意这里返回的引用/指针,相当于e := &Employee{}
    e2.Id = "2" // 与其他主要编程语言的差异,通过实例的指针访问成员不需要使用->
    e2.Age = 22
    e2.Name = "Rose"

    检验一下类型

        t.Logf("e is %T", e)
        t.Logf("e2 is %T", e2)

    === RUN TestCreateEmployeeObj
    --- PASS: TestCreateEmployeeObj (0.00s)
    func_test.go:79: e is fun_test.Employee
    func_test.go:80: e2 is *fun_test.Employee
    PASS

    行为(方法)定义

    与其他主要编程语言的差异

    两种方式定义行为:

    // 第一种定义方式在实例对应方法被调用时,实例成员会进行值复制
    func (e Employee) String() string  {
        return fmt.Sprintf("ID:%s-Name:%s-Age:%d", e.Id, e.Name, e.Age)
    }
    
    // 通常情况下为了避免内存拷贝我们使用第二种定义方式
    func (e *Employee) String() string {
        return fmt.Sprintf("ID:%s/Name:%s/Age:%d", e.Id, e.Name, e.Age)
    }

    接口

    定义交互协议

    Java

                                                 

    如果把AClient和接口A打包在一起为packageA,Almpl打包为B

    那么A和B 是相互依赖的

    一般是接口独立在一个package中,解决循环依赖

    Go

    Duck Type式接口实现

     没有显示表明实现接口,只是实现了接口的方法WriteHelloWorld()

    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 = new(GoProgrammer)
        t.Log(p.WriteHelloWorld())
    }

    === RUN TestClient
    --- PASS: TestClient (0.00s)
    func_test.go:117: fmt.println("Hello World")
    PASS

    与其他主要编程语言的差异

    1.接口为非入侵性,实现不依赖于接口定义

    2.所以接口的定义可以包含在接口使用者包内

    接口变量

     自定义类型

    1.type IntConvertionFn func(n int) int

    2.type MyPoint int

    func timeSpent(inner func(op int)int) func(opt int) int  {
        return func(n int) int {
            start := time.Now()
            ret := inner(n)
    
            fmt.Println("time spent:", time.Since(start).Seconds())
            return ret
        }
    }

    参数特别长,自定义一个类型

    type IntConv func(op int) int 
    
    func timeSpent(inner IntConv) func(opt int) int  {
        return func(n int) int {
            start := time.Now()
            ret := inner(n)
    
            fmt.Println("time spent:", time.Since(start).Seconds())
            return ret
        }
    }

    扩展和复用

    争议最大的一块

    Go不支持继承

    Java代码

    class Pet {
        public void speak(){
            System.out.print("...");
        }
        public void speakTo(String name){
            this.speak();
            System.out.println(name);
        }
    }
    
    class Dog extends Pet{
        @Override
        public void speak(){
            System.out.println("Wang!");
        }
    }
    
    public class InheritanceTest{
    
        private void makePetSpeak(Pet p){
            p.speak();
            System.out.println("
    Pet speak.");
        }
    
        @Test
        public void  testSubClassAccess(){
            Pet aDog = new Dog();
            aDog.speak();
            aDog.speakTo("Chao");
        }
        @Test
        public void testLSP(){
            Dog aDog = new Dog();
            makePetSpeak(aDog);
        }
    }

     makePetSpeak()的参数是Pet类型,接收子类Dog类型是可以的,且会调用Dog的speak

     在Go中做同样的事情

    使用内嵌

    没有继承

    dog只能再重写个不同的SpeakTo方法

    type Pet struct {
    
    }
    
    func (p *Pet)Speak()  {
    	fmt.Print("...")
    }
    
    func (p *Pet)SpeakTo(host string)  {
    	p.Speak()
    	fmt.Println(" ", host)
    }
    
    type Dog struct {
    	p *Pet
    }
    
    func (d *Dog)Speak()  {
    	fmt.Println("Wang")
    }
    
    func (d *Dog)SpeakTo(host string)  {
    	d.Speak()
    	//d.p.SpeakTo(host)
       fmt.Println(" ", host)
    }
    
    func TestDog(t *testing.T){
       dog := new(Dog)
       dog.SpeakTo("chao")
    
    }
    

      

    多态

    想支持多态,要使用接口

     

     空接口与断言

    1.空接口可以表示任何类型

    2.通过断言来将空接口转换为定制类型

    v, ok := p.(int) // ok=true 时则为转换成功

    func DoSomething(p interface{})  {
        if i, ok := p.(int); ok{
            fmt.Println("Integer", i)
            return
        }
        if s, ok := p.(string); ok{
            fmt.Println("string", s)
            return
        }
        fmt.Println("Unknow Type")
    }
    
    func TestEmptyInterfaceAssertion(t *testing.T)  {
        DoSomething(10)
        DoSomething("10")
    }

    === RUN TestEmptyInterfaceAssertion
    Integer 10
    string 10
    --- PASS: TestEmptyInterfaceAssertion (0.00s)
    PASS

    用switch可以简化上面代码

    func DoSomething(p interface{})  {
        switch v := p.(type) {
        case int:
            fmt.Println("Integer", v)
        case string:
            fmt.Println("String", v)
        default:
            fmt.Println("Unknown Type")
        }
    }
    
    func TestEmptyInterfaceAssertion(t *testing.T)  {
        DoSomething(10)
        DoSomething("10")
    }

     Go接口最佳实践

  • 相关阅读:
    Linux产生coredump文件(core)
    shell脚本每五分钟执行一次可执行程序(nohup)
    VIM快捷操作
    日期正则表达式
    istringstream字符串流对象
    json和pickle模块
    sys模块
    random模块
    time模块
    python的模块
  • 原文地址:https://www.cnblogs.com/aidata/p/11921857.html
Copyright © 2011-2022 走看看