一、感受接口

type Usb interface {
Connect()
Disconnect()
}
// 手机
type Phone struct {}
// 相机
type Camera struct {}
// 计算机
type Computer struct {}
// 手机实现接口所有方法
func (p Phone) Connect() {
fmt.Println("手机连接中...")
}
func (p Phone) Disconnect() {
fmt.Println("手机断开连接中...")
}
// 相机实现接口所有方法
func (c Camera) Connect() {
fmt.Println("相机连接中...")
}
func (c Camera) Disconnect() {
fmt.Println("相机断开连接中...")
}
// Working方法,接收一个Usb接口类型变量
func (c Computer) Working(usb Usb) {
// 通过接口变量来调用Connect和Disconnect方法
usb.Connect()
usb.Disconnect()
}
func main() {
// 创建结构体实例
phone := Phone{}
camera := Camera{}
computer := Computer{}
// 关键点
computer.Working(phone)
computer.Working(camera)
}
// 输出如下
// 手机连接中...
// 手机断开连接中...
// 相机连接中...
// 相机断开连接中...

当传入一个phone,usb就能识别是手机,传入camera,usb就能识别是相机,并别分调用其相应的方法。这很明显就是多态呀!!!

func (c Computer) Working(usb Usb) {
usb.Connect()
usb.Disconnect()
}
func main() {
phone := Phone{}
camera := Camera{}
computer := Computer{}
computer.Working(phone)
computer.Working(camera)
}

二、接口介绍

interface 类型可以定义一组方法,但是这些方法不需要实现。只要一个变量,含有接口类型中的所有方法,那么这个变量就实现了这个接口。

语法:

type 接口名 interface {
method1(参数列表) 返回值列表
method2(参数列表) 返回值列表
...
}

三、注意事项和细节

  1. 接口本身不能创建实例,但是可以指向一个实现了该接口的自定义类型的实例;
  2. 接口中所有的方法都没有方法体,即只定义方法,没有实现该方法;
  3. 一个自定义类型只有实现了某个接口,才能将该自定义类型的实例赋给该接口类型;
  4. 只要是自定义数据类型,就可以实现接口,不仅仅是结构体类型;
  5. 一个自定义类型可以实现多个接口;
  6. golang的接口不能有任何变量;
  7. 一个接口(比如 C 接口)可以继承多个别的接口(比如 A、B 接口),这时如果要实现 C 接口,也必须将 A、B 接口中的方法也实现;注意,A、B接口中不能有相同的方法,相当于 C 接口有两个相同的方法,这是不允许的;
  8. interface 类型默认是一个指针(引用类型),如果没有对 interface 初始化就使用,那么会输出 nil ;
  9. 空接口 interface{} 没有任何方法,因此所有类型都实现了空接口,即可以把任何一个变量赋给空接口;
  10. 如果一个自定义类型是使用指针方式实现一个接口的,那么需要将该自定义类型的地址赋给该接口,不然会报错。
type AInterface interface {
Eat()
} type Person struct {
Name string
} func (p Person) Eat() {
fmt.Printf("%s正在吃饭...\n", p.Name) // 佩奇正在吃饭...
} func main() {
p := Person{"佩奇"}
var a AInterface = p // 接口可以指向一个实现了该接口的自定义类型实例
a.Eat()
}

第1、3点

type AInterface interface {
Eat()
} type BInterface interface {
Sleep()
} type Person struct {
Name string
} func (p Person) Eat() {
fmt.Printf("%s正在吃饭...\n", p.Name) // 佩奇正在吃饭...
} func (p Person) Sleep() {
fmt.Printf("%s正在睡觉...\n", p.Name) // 佩奇正在睡觉...
} func main() {
p := Person{"佩奇"}
var a AInterface = p
var b BInterface = p
a.Eat()
b.Sleep()
}

第5点

type AInterface interface {
Eat()
} type BInterface interface {
Sleep()
} type CInterface interface {
AInterface
BInterface
Study()
} type Person struct {
Name string
} func (p Person) Eat() {
fmt.Printf("%s正在吃饭...\n", p.Name) // 佩奇正在吃饭...
} func (p Person) Sleep() {
fmt.Printf("%s正在睡觉...\n", p.Name) // 佩奇正在吃饭...
} func (p Person) Study() {
fmt.Printf("%s正在学习...\n", p.Name) // 佩奇正在学习...
} func main() {
p := Person{"佩奇"}
var c CInterface = p
c.Eat()
c.Sleep()
c.Study()
}

第7点

type T interface {}

type Integer int

func main() {
var int1 Integer
int2 := Integer(100)
var t T
t = int1
fmt.Println(t) //
t = int2
fmt.Println(t) //
}

第9点

type A interface {
Eat()
} type Person struct {
Name string
} // 使用 Person 指针类型实现一个接口的方法
func (p *Person) Eat() {
fmt.Printf("%s正在吃饭...", p.Name)
} func main() {
p := Person{"佩奇"}
//var a A = p // 错误!!!因为Person类型没有实现A接口,修改如下
var a A = &p
a.Eat()
}

第10点

四、接口最佳实践

实现对 Student 结构体切片的排序:sort.Sort(data Interface)

package main

import (
"fmt"
"math/rand"
"sort"
"time"
) type Student struct {
Name string
Score int
} type StudentSlice []Student func (ss StudentSlice) Len() int {
return len(ss)
}
// Less方法决定使用什么标准进行排序
// 这里按成绩从小到大排序
func (ss StudentSlice) Less(i, j int) bool {
return ss[i].Score < ss[j].Score
}
func (ss StudentSlice) Swap(i, j int) {
ss[i], ss[j] = ss[j], ss[i]
} func main() {
var ss StudentSlice
rand.Seed(time.Now().UnixNano())
for i := 0; i < 10; i++ {
student := Student{
Name: fmt.Sprintf("学生%d号", i),
Score: rand.Intn(100),
}
ss = append(ss, student)
}
// 排序前的顺序
for _, v := range ss {
fmt.Println(v)
}
// 调用sort.Sort方法
sort.Sort(ss)
fmt.Println()
// 排序后的顺序
for _, v := range ss {
fmt.Println(v)
}
}

输出结果:

五、接口与继承的区别

package main

import "fmt"

type Monkey struct {
Name string
} type LittleMonkey struct {
Monkey // 继承
} type BridAble interface {
Flying()
}
type FishAble interface {
Swimming()
} func (m *Monkey) Climbing() {
fmt.Printf("%s天生就会爬树...\n", m.Name)
} func (ls *LittleMonkey) Flying() {
fmt.Printf("%s通过学习,会飞翔...\n", ls.Name)
} func (ls *LittleMonkey) Swimming() {
fmt.Printf("%s通过学习,会游泳...\n", ls.Name)
} func main() {
wk := LittleMonkey{Monkey{"小猴子"}}
wk.Climbing()
wk.Flying()
wk.Swimming()
}

代码小结:

  1. 当 B 结构体继承了 A 结构体,那么 B 结构体就"拥有"了 A 结构体的字段和方法,并且可以直接使用;
  2. 当 B 结构体需要扩展功能,同时不希望去破坏继承关系,则实现某个接口即可。因此可以认为:实现接口可以看做是对继承的一种补充。

接口与继承总结:

①接口与继承解决的问题不同

  • 继承的价值主要在于:解决代码的复用性可维护性
  • 接口的价值主要在于:设计,设计好各种规范(方法),让其它自定义类型去实现这些方法。

②接口比继承更加灵活

  • 继承是 is - xx 的关系,而接口是 like - xx 的关系。为什么这样说? --> 我们不能说猴子是一条鱼,但可以说:猴子可以像鱼儿一样游泳。

③接口在一定程度上实现代码解耦

GO:interface的更多相关文章

  1. iOS开发工具Xcode:Interface Builder

    简介: Interface Builder(IB)是Mac OS X平台下用于设计和测试用户界面(GUI)的应用程序(非开源).为了生成GUI,IB并不是必需的,实际上Mac OS X下所有的用户界面 ...

  2. 面向对象_06【抽象类:abstract、接口:interface、实现:implements】

    抽象类:abstract抽象:没有足够的描述功能,事物不具体的描述,却又有共性. 特点: 1,方法只有声明没有实现时,该方法就是抽象方法,需要被abstract修饰,抽象方法必须定义在抽象类中,该类也 ...

  3. 静态,关键字:static 接口,IUSB , API 接口关键字:interface

    //静态 //普通成员 //普通成员是属于对象的 //静态成员 //静态成员属于类的 //关键字:static //self关键字:在类里面代表该类 //在静态方法里面不能调用普通成员 //在普通方法 ...

  4. [你必须知道的.NET]第二十七回:interface到底继承于object吗?

    发布日期:2009.03.05 作者:Anytao © 2009 Anytao.com ,Anytao原创作品,转贴请注明作者和出处. 说在,开篇之前 在.NET世界里,我们常常听到的一句话莫过于“S ...

  5. go:interface{}、断言与类型转换

    interface{}可用于向函数传递任意类型的变量,但对于函数内部,该变量仍然为interface{}类型(空接口类型), 不清楚这点将可能导致错误.如以下代码: package main impo ...

  6. java8新特性:interface中的static方法和default方法

    java8中接口有两个新特性,一个是静态方法,一个是默认方法. static方法 java8中为接口新增了一项功能:定义一个或者多个静态方法. 定义用法和普通的static方法一样: public i ...

  7. Go语言第一深坑:interface 与 nil 的比较

    interface简介 Go 语言以简单易上手而著称,它的语法非常简单,熟悉 C++,Java 的开发者只需要很短的时间就可以掌握 Go 语言的基本用法. interface 是 Go 语言里所提供的 ...

  8. java基础13 接口(及关键字:interface、implements)

    接口 1.接口的定义格式 interface 接口名{ } interface :接口的关键字 implements:实现接口的关键字 2.接口的作用 1.程序的解耦.(低耦合)        2.定 ...

  9. 面试题思考:interface和abstract的区别

    抽象类(abstract) 含有abstract修饰符的class即为抽象类,abstract 类不能创建的实例对象. 含有abstract方法的类必须定义为abstract class,abstra ...

  10. 注解:@interface 自定义注解的语法

      自定义注解: 使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节.在定义注解时,不能继承其他的注解或接口 ...

随机推荐

  1. mongodb 安装问题

    重新安装一台机器时出现头疼的问题,老是说什么 dbpath 不存在 结果最后发现是没有写 mongodb.log 这个log文件名 1. 创建 datas 文件夹  e:\mongodb\datas ...

  2. java final static 和final区别

    static 和非static 之间的差异,只有当值在运行期间初始化的前提下,这种差异才会揭示出来.因为编译期间的值被编译器认为是相 同的. package thinking; public clas ...

  3. the little schemer 笔记(10)

    第十章 What Is  the Value of All of This? entry条目 是由list表组成的 pair 对,pair 对的第一个list表是集合 set.另外,两个list表的长 ...

  4. 《统计学习方法》笔记三 k近邻法

    本系列笔记内容参考来源为李航<统计学习方法> k近邻是一种基本分类与回归方法,书中只讨论分类情况.输入为实例的特征向量,输出为实例的类别.k值的选择.距离度量及分类决策规则是k近邻法的三个 ...

  5. 洛谷 P3312 [SDOI2014]数表

    式子化出来是$\sum_{T=1}^m{\lfloor}\frac{n}{T}{\rfloor}{\lfloor}\frac{m}{T}{\rfloor}\sum_{k|T}\mu(\frac{T}{ ...

  6. Substring CodeForces - 919D

    http://codeforces.com/problemset/problem/919/D 就是先判环,如果有环就-1,否则对每个字母分开跑一下dp 错误记录: 1.有向图判环,自环一定要特判!(不 ...

  7. [已读]HTML5与CSS3权威指南第二版(下)

    去年下半年前公司给买的(老付对我们确实蛮好的),一人挑一本,我当时一定是秀逗了.看的时候就发现,这本书的内容过时严重,即便它是新出不久的第.二.版.其他没什么说的,总之,不推荐看.

  8. 搜狐前端css常用命名

  9. innobackupex的使用

    优点: 不暂停服务器创建Innodb热备份 为mysql做增量的备份 在mysql服务器之间做在线表迁移 使创建mysql replication更加容易 备份mysql但不增加服务器的负载 安装:x ...

  10. ubuntu 16.0.4安装MySQL5.7

    系统版本 root@sishen:~# uname -a Linux sishen 4.10.0-35-generic #39~16.04.1-Ubuntu SMP Wed Sep 13 09:02: ...