Skip to content

十五、多态

wenjianzhang edited this page Nov 12, 2019 · 3 revisions

多态

package polymorphsim_test

import (
	"fmt"
	"testing"
)

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

type GoProgarmmer struct {
}

func (goo *GoProgarmmer) WriteHelloWorld() Code {
	return "fmt.Println(\"Hello World\")"
}

type JavaProgarmmer struct {
}

func (goo *JavaProgarmmer) WriteHelloWorld() Code {
	return "System.out.Println(\"Hello World\")"
}

func writeFirstProgram(p Progarmmer)  {
	fmt.Printf("%T %v\n",p, p.WriteHelloWorld())
}

func TestClient(t *testing.T) {
	goProg := new(GoProgarmmer)
	javaProg := new(JavaProgarmmer)
	writeFirstProgram(goProg)
	writeFirstProgram(javaProg)
}

输出

=== RUN   TestClient
*polymorphsim_test.GoProgarmmer fmt.Println("Hello World")
*polymorphsim_test.JavaProgarmmer System.out.Println("Hello World")
--- PASS: TestClient (0.00s)
PASS

Process finished with exit code 0

空接口与断言

  • 空接口可以表示任何类型
  • 通过断言来讲空接口转换为制定类型
v, ok := p.(int) // ok=true 时为转换成功

v 代表转换后的结果值,ok代表是否成功

示例代码

package empty_interface

import (
	"fmt"
	"testing"
)

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")

	switch v:=p.(type) {
	case int:
		fmt.Println("Integer",v)
	case string:
		fmt.Println("string",v)
	default:
		fmt.Println("Unknow Type")
	}
}

func TestEmptyInterfaceAssertion(t *testing.T)  {
	DoSomething(10)
	DoSomething("10")
}

输出

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

Process finished with exit code 0

Go 接口最佳实践

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

type Reader interface {
  Read(p []byte) (n int, err error)
}

type Writer interface {
  Write(p []byte) (n int, err error)
}

较大的接口定义,可以由多个小接口定义组合而成

type ReadWriter interface {
  Reader
  Writer
}

只依赖于必要功能的最小接口

func StoreData(reader Reader) error {
  ...
}
Clone this wiki locally