interface是golang的抽象设计的根基,是方法集合的接口,是一个非常强大的并且规范的指针,可以引用任意实现了该接口的方法集合的struct,不能定义属性,意味着在抽象设计里是不允许有数据的,使语言的编译运行管理更纯粹方便。
一切属性都是setter/getter
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| package main type Surface struct{ skin string } func (s *Surface) Skin() string{ return "My skin is " + s.skin } type Men interface { GetSurface() Surface } type European struct { surface Surface } func (p *European) GetSurface() Surface{ return p.surface } type African struct { surface Surface } func (p *African) GetSurface() Surface{ return p.surface } func Introduce(men Men){ s := men.GetSurface() println(s.Skin()) } func main() { var s Surface s = Surface{"white"} e := European{s} Introduce(&e) s = Surface{"black"} a := African{s} Introduce(&a) }
|
上例中的多态,通过setter/getter变相完成了property在interface定义,用方法多态来实现属性多态。
父类方法A调用子类方法B
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| package main type Men interface { Age() int } type Parent struct { Men m Men } func (p *Parent) Age() int{ return 80 } func (p *Parent) Display1() { println(p.Men.Age()) } func (p *Parent) Display2() { println(p.m.Age()) } type Child struct { Parent } func (c *Child) Age() int{ return 40 } func main() { var child *Child var parent *Parent parent = &Parent{parent, nil} child = &Child{Parent: *parent} println("====parent") child.Display1() parent = &Parent{child, nil} child = &Child{Parent: *parent} println("====child") child.Display1() child.m = parent println("====parent") child.Display2() child.m = child println("====child") child.Display2() }
|
上例中的实现了在父类的A方法中调用父类或者子类的B方法,类似于抽象方法。因为go是静态语言,没有动态语言强大的查找机制,也没有虚函数(virtural method)和抽象方法(abstract method)之类的辅助高级别的多态。
幸好,golang有指针,即interface,又名接口,通过在父类定义接口类型的属性,并在实例化的时候动态绑定该属性的真正类型,来完成父类方法中一些多态方法的灵活调用,增加了公共部分的复用性。