一、感受接口

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. bzoj 3667: Rabin-Miller算法【Miller-Rabin】

    Miller-Rabin模板 #include<iostream> #include<cstdio> #include<algorithm> using names ...

  2. Integer Cache(带你脱坑)

    Integer Cache 废话不多说----->直接上代码: public class IntegerDemo { public static void main(String[] args) ...

  3. iOS 让部分ViewController支持屏幕旋转

    首先,在Xcode里设置整个项目支持的屏幕显示方向: 然后创建一个UINavigationController的子类,然后重载以下属性: 对于需要自定义屏幕方向的ViewController,重载这个 ...

  4. selenium中Xpath和CSS Selector的使用方法

    一.selenium中Xpath的使用方法 1. 什么是xpath? Xpath是XML的路径语言,通俗一点讲就是通过元素的路径来查找这个标签元素 2. 练习Xpath的工具 火狐浏览器,下载插件Fi ...

  5. [Usaco2015 Feb]Censoring

    Description Farmer John has purchased a subscription to Good Hooveskeeping magazine for his cows, so ...

  6. Query on a tree IV SPOJ - QTREE4

    https://vjudge.net/problem/SPOJ-QTREE4 点分就没有一道不卡常的? 卡常记录: 1.把multiset换成手写的带删除堆(套用pq)(作用很大) 2.把带删除堆里面 ...

  7. Codeforces Round #325 (Div. 2)

    水 A - Alena's Schedule /************************************************ * Author :Running_Time * Cr ...

  8. VMware Workstation虚拟磁盘文件备份或移植

    一.备份快照 1> 1.点击虚拟机上面的快速备份按钮 2.填写快照名字和备注 快照就生成了. 2>恢复 1.点击恢复按钮,此按钮的功能是直接恢复到上一次备份的节点. 2.或者选后面一个按钮 ...

  9. Git之删除本地和远程项目

    目录 删除本地项目 删除远程项目 删除本地项目: git rm -rf project  或者 rm -rf project   [删除工作区项目] git add project [将删除的项目添加 ...

  10. 洛谷P2770 航空路线问题(费用流)

    题意 $n$个点从左向右依次排列,有$m$条双向道路 问从起点到终点,再从终点回到起点,在经过的点不同的情况下最多能经过几个点 Sol 首先,问题可以转化为求两条互不相交的路径,使得点数最多 为了满足 ...