本文共 4530 字,大约阅读时间需要 15 分钟。
面向对象世界中的接口的一般定义是“接口定义对象的行为”。它只指定对象应该做什么。实现这种行为的方法(实现细节)是针对对象的。
在Go中,接口是一组方法签名。当类型为接口中的所有方法提供定义时,它被称为实现接口。它与OOP非常相似。接口指定了类型应该具有的方法,类型决定了如何实现这些方法。
它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口
接口定义了一组方法,如果某个对象实现了某个接口的所有方法,则此对象就实现了该接口。
定义接口
/* 定义接口 */type interface_name interface { method_name1 [return_type] method_name2 [return_type] method_name3 [return_type] ... method_namen [return_type]}/* 定义结构体 */type struct_name struct { /* variables */}/* 实现接口方法 */func (struct_name_variable struct_name) method_name1() [return_type] { /* 方法实现 */}...func (struct_name_variable struct_name) method_namen() [return_type] { /* 方法实现*/}
示例代码:
package mainimport ( "fmt")type Phone interface { call()}type NokiaPhone struct { }func (nokiaPhone NokiaPhone) call() { fmt.Println("I am Nokia, I can call you!")}type IPhone struct { }func (iPhone IPhone) call() { fmt.Println("I am iPhone, I can call you!")}func main() { var phone Phone phone = new(NokiaPhone) phone.call() phone = new(IPhone) phone.call()}
运行结果:
I am Nokia, I can call you!I am iPhone, I can call you!
package mainimport "fmt"type Human struct { name string age int phone string}type Student struct { Human //匿名字段 school string loan float32}type Employee struct { Human //匿名字段 company string money float32} //Human实现Sayhi方法func (h Human) SayHi() { fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)} //Human实现Sing方法func (h Human) Sing(lyrics string) { fmt.Println("La la la la...", lyrics)} //Employee重写Human的SayHi方法func (e Employee) SayHi() { fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name, e.company, e.phone) //Yes you can split into 2 lines here.}// Interface Men被Human,Student和Employee实现// 因为这三个类型都实现了这两个方法type Men interface { SayHi() Sing(lyrics string)}func main() { mike := Student{ Human{ "Mike", 25, "222-222-XXX"}, "MIT", 0.00} paul := Student{ Human{ "Paul", 26, "111-222-XXX"}, "Harvard", 100} sam := Employee{ Human{ "Sam", 36, "444-222-XXX"}, "Golang Inc.", 1000} Tom := Employee{ Human{ "Sam", 36, "444-222-XXX"}, "Things Ltd.", 5000} //定义Men类型的变量i var i Men //i能存储Student i = mike fmt.Println("This is Mike, a Student:") i.SayHi() i.Sing("November rain") //i也能存储Employee i = Tom fmt.Println("This is Tom, an Employee:") i.SayHi() i.Sing("Born to be wild") //定义了slice Men fmt.Println("Let's use a slice of Men and see what happens") x := make([]Men, 3) //T这三个都是不同类型的元素,但是他们实现了interface同一个接口 x[0], x[1], x[2] = paul, sam, mike for _, value := range x { value.SayHi() }}
运行结果:
This is Mike, a Student: Hi, I am Mike you can call me on 222-222-XXX La la la la... November rain This is Tom, an Employee: Hi, I am Sam, I work at Things Ltd.. Call me on 444-222-XXX La la la la... Born to be wild Let's use a slice of Men and see what happens Hi, I am Paul you can call me on 111-222-XXX Hi, I am Sam, I work at Golang Inc.. Call me on 444-222-XXX Hi, I am Mike you can call me on 222-222-XXX
那么interface里面到底能存什么值呢?如果我们定义了一个interface的变量,那么这个变量里面可以存实现这个interface的任意类型的对象。例如上面例子中,我们定义了一个Men interface类型的变量m,那么m里面可以存Human、Student或者Employee值
当然,使用指针的方式,也是可以的
但是,接口对象不能调用实现对象的属性
interface函数参数
interface的变量可以持有任意实现该interface类型的对象,这给我们编写函数(包括method)提供了一些额外的思考,我们是不是可以通过定义interface参数,让函数接受各种类型的参数
嵌入interface
package mainimport "fmt"type Human interface { Len()}type Student interface { Human}type Test struct { }func (h *Test) Len() { fmt.Println("成功")}func main() { var s Student s = new(Test) s.Len()}
运行结果:
成功
示例代码:
package testimport ( "fmt")type Controller struct { M int32}type Something interface { Get() Post()}func (c *Controller) Get() { fmt.Print("GET")}func (c *Controller) Post() { fmt.Print("POST")}
package mainimport ( "fmt" "test")type T struct { test.Controller}func (t *T) Get() { //new(test.Controller).Get() fmt.Print("T")}func (t *T) Post() { fmt.Print("T")}func main() { var something test.Something something = new(T) var t T t.M = 1 // t.Controller.M = 1 something.Get()}
示例代码:
T
Controller实现了所有的Something接口方法,当结构体T中调用Controller结构体的时候,T就相当于Java中的继承,T继承了Controller,因此,T可以不用重写所有的Something接口中的方法,因为父构造器已经实现了接口。
如果Controller没有实现Something接口方法,则T要调用Something中方法,就要实现其所有方法。
如果something = new(test.Controller)
则调用的是Controller中的Get方法。
T可以使用Controller结构体中定义的变量
接口对象不能调用接口实现对象的属性
转载地址:http://amwji.baihongyu.com/