6.4 不一样的接口类型,一样的多态

peter
• 阅读 1291

多态

多态是一个比较好理解的概念,直接看测试代码 1,感受一下

package polymorphism

import (
    "fmt"
    "testing"
)

type Code string
type Programmer interface {
    WriteHelloWorld() Code
}

type GoProgrammer struct {

}

func (p *GoProgrammer) WriteHelloWorld() Code  {
    return "fmt.Println(\"Hello World!\")"
}

type JavaProgrammer struct {

}

func (p *JavaProgrammer) WriteHelloWorld() Code  {
    return "System.out.println(\"Hello World!\")"
}

// %T 输出传入参数的类型
func writeFirstProgram(p Programmer) {
    fmt.Printf("%T %v\n", p, p.WriteHelloWorld())
}

func TestPolymorphism(t *testing.T) {
    goProg := new(GoProgrammer)
    javaProg := new(JavaProgrammer)
    writeFirstProgram(goProg)  // *polymorphism.GoProgrammer fmt.Println("Hello World!")
    writeFirstProgram(javaProg)  // *polymorphism.JavaProgrammer System.out.println("Hello World!")
}

空接口和断言

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

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

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

测试实例 2

package empty_interface

import (
    "fmt"
    "testing"
)

func DoSomeThing(p interface{}) {
    //if i, ok := p.(int); ok {
    //    fmt.Println("Integer ", i)
    //    return
    //}
    //if i, ok := p.(string); ok {
    //    fmt.Println("String ", i)
    //    return
    //}
    //fmt.Println("Unknown Type")
    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)   // Integer 10
    DoSomeThing("10") // String 10
}

Go 接口最佳实践

  1. 倾向于使用小的接口定义,很多接口只包含一个方法

    type Reader interface {
      Read(p []byte) (n int, err error)
    }
    
    type Write interface {
      Write(p []byte) (n int, err error)
    }
  2. 较大的接口定义,可以由多个小接口定义组合而成

    type ReadWriter interface {
      Reader
      Writer
    }
  3. 只依赖于必要功能的最小接口

    func StoreData(reader Reader) error {
      ...
    }
点赞
收藏
评论区
推荐文章

暂无数据