博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Go学习(11):接口
阅读量:4060 次
发布时间:2019-05-25

本文共 4530 字,大约阅读时间需要 15 分钟。

接口

1.1 什么是接口?

面向对象世界中的接口的一般定义是“接口定义对象的行为”。它只指定对象应该做什么。实现这种行为的方法(实现细节)是针对对象的。

在Go中,接口是一组方法签名。当类型为接口中的所有方法提供定义时,它被称为实现接口。它与OOP非常相似。接口指定了类型应该具有的方法,类型决定了如何实现这些方法。

它把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实现了这个接口

接口定义了一组方法,如果某个对象实现了某个接口的所有方法,则此对象就实现了该接口。

1.2 接口的定义语法

定义接口

/* 定义接口 */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!
  • interface可以被任意的对象实现
  • 一个对象可以实现任意多个interface
  • 任意的类型都实现了空interface(我们这样定义:interface{}),也就是包含0个method的interface

1.3 interface值

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/

你可能感兴趣的文章
项目导入时报错:The import javax.servlet.http.HttpServletRequest cannot be resolved
查看>>
linux对于没有写权限的文件如何保存退出vim
查看>>
Windows下安装ElasticSearch6.3.1以及ElasticSearch6.3.1的Head插件
查看>>
IntelliJ IDEA 下的svn配置及使用的非常详细的图文总结
查看>>
【IntelliJ IDEA】idea导入项目只显示项目中的文件,不显示项目结构
查看>>
ssh 如何方便的切换到其他节点??
查看>>
JSP中文乱码总结
查看>>
Java-IO-File类
查看>>
Java-IO-java的IO流
查看>>
Java-IO-输入/输出流体系
查看>>
Java实现DES加密解密
查看>>
HTML基础
查看>>
Java IO
查看>>
Java NIO
查看>>
Java大数据:Hbase分布式存储入门
查看>>
Java大数据:全文搜索引擎Elasticsearch入门
查看>>
大数据学习:Hadoop入门学习书单
查看>>
大数据学习:Spark SQL入门简介
查看>>
大数据学习:Spark RDD操作入门
查看>>
大数据框架:Spark 生态实时流计算
查看>>