golang的多态特性主要体现在接口上;
主要优势:高内聚低耦合;
package main import ( "fmt" ) type usb interface { start() stop() } type phone struct { } func (p phone) start() { fmt.Println("手机开始工作") } func (p phone) stop() { fmt.Println("手机停止工作") } type camera struct { } func (c camera) start() { fmt.Println("相机开始工作") } func (c camera) stop() { fmt.Println("相机停止工作") } type computer struct { } func (co computer) working(usb usb) { usb.start() usb.stop() } func main() { computer := computer{} phone := phone{} camera := camera{} computer.working(phone) computer.working(camera) }
接口的注意事项:
- 接口本身不能创建实例,但是可以指向一个实现了该接口的自定义类型的变量;
- 接口中的所有方法都没有方法体,即都是没有实现的方法;
- 一个自定义类型需要将某个接口的所有方法都实现;
- 一个自定义类型只有实现了某个接口,才能将该自定义类型的实例赋值给接口类型;
- 只要是自定义数据类型就可以实现接口,不仅仅是结构体类型;
- 一个自定义类型可以实现多个接口;
- 接口中不能有任何变量;
- 一个接口可以继承多个别的接口,这时如果要实现该接口,则必须实现继承来的所有接口中的方法;
- interface类型默认是一个指针,如果没有对Interface进行初始化就使用,就会输出nil;
- 空接口没有任何方法,所有数据类型都实现了空接口;
var a interface{} - 一个接口中不能有多个相同名字的方法;
接口的经典实例:实现对hero结构体切片进行排序;
golang中在sort包里面有一个Sort函数,可以定制自己的排序操作,只不过所传入的变量需要实现三个接口方法:Len、Less、Swap。其中Len()用于计算变量的长度,Less()指定对哪个字段进行排序,且按升序还是降序排序,Swap()用于交换两个变量的值。
接口和继承之间的关系?
接口是对继承的一种补充。通过接口,可以在不破坏原有父类属性和方法的基础上,给子类添加新的功能,同时这所有的功能也都可以继续被下一级所继承。
让我们捋一捋之间的关系:
- 首先,有一个monkey父类,包含属性:名字;
- littleMonKey继承了该类,获得了名字,它有属于自己的方法climbing;
- 但是flying和swimming本身并不属于littleMonkey,我们不能让它们变为littleMonkey的方法,于是我们实现了两个接口;这样littleMonkey得到了扩展;而flying和swimming仍然可以被其它的对象所使用;
- offspring继承了littleMonkey;offspring拥有monkey变量的属性:name,拥有littleMonkey的方法climbing,同时,它也拥有flying和swimming属性;
- 可以想象成,一直猴子生下了孙悟空,孙悟空虽然学会了飞和游泳,但并没有改变他还是猴子的事实,最后悟空的后代也可以学会飞和游泳,但也拥有猴子的特性;
在将一个例子,比如说有下面的关系:
我们想让足球运动员和大学生学英语:
(1)将英语写到运动员中,但是篮球运动员也能学英语了;
(2)将英语写到学生中,但是中学生也能学英语;
(3)将英语各自写到足球运动员和大学生中,有可能导致学英语的方法不一样;
(4)定义一个学英语的接口,让足球运动员和大学生实现,具有一定的规范性;
继承和接口的解决问题不同:
继承:解决代码的复用性和可维护性;
接口:设计,设计好各种规范,让其他自定义类型去实现这些方法;接口更加灵活;在一定程度上实现代码解耦;