这篇记录面向对象编程的写法,类、接口、多态、不支持继承。
基础知识
- 接口定义对象之间的交互协议,go 接口为非入侵性,实现不依赖于接口定义;接口的定义可以包含在接口使用者包内。
- 面向对象的扩展一般通过复合或继承来实现,go 本身不支持继承。
- 空接⼝可以表示任何类型;通过断⾔来将空接⼝转换为制定类型。i, ok := p.(int) // ok=true时转换成功
- Go 接⼝最佳实践:倾向于使⽤⼩的接⼝定义,很多接⼝只包含⼀个⽅法;较⼤的接⼝定义,可以由多个⼩接⼝定义组合⽽成;只依赖于必要功能的最⼩接⼝。
简单语法示例
类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| type Employee struct { Id string Name string Age int } func TestCreateEmployeeObj(t *testing.T) { e := Employee{"0", "Bob", 20} e1 := Employee{Name: "Mike", Age: 30} e2 := new(Employee) e2.Name = "Rose" t.Logf("e is %T", e) t.Logf("e2 is %T", e2) }
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) }
|
接口 & 多态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| 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 (p *JavaProgrammer) WriteHelloWorld() Code { return "System.out.Println(\"Hello World!\")" } func writeFirstProgrammer(p Programmer) { fmt.Printf("%T %v\n", p, p.WriteHelloWorld) } func TestClient(t *testing.T) { goProg := &GoProgrammer{} javaProg := new(JavaProgrammer) writeFirstProgram(goProg) writeFirstProgram(javaProg) }
|
继承的实现(本身不支持)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| 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() { d.p.Speak() }
type Dog struct { Pet } func (d *Dog) Speak() { fmt.Print("Wang!") } func TestDog(t *testing.T) { dog := new(Dog) dog.SpeakTo("Chao") }
|
空接口
空接口可以表示任意类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| func DoSomething(p interface{}) { 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") }
|