一、感受接口

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. echartShow

    echartShow 基于echart和bootstrap的大屏展示 以下是已经运用的成品图片.有一些数据运用的是json文件,实际成品中运用的是真实数据,除了公司内网访问不了.  需注意的地方 图表 ...

  2. Hdu 5439 Aggregated Counting (2015长春网络赛 ACM/ICPC Asia Regional Changchun Online 找规律)

    题目链接: Hdu 5439 Aggregated Counting 题目描述: 刚开始给一个1,序列a是由a[i]个i组成,最后1就变成了1,2,2,3,3,4,4,4,5,5,5.......,最 ...

  3. Educational Codeforces Round 46 (Rated for Div. 2) C. Covered Points Count

    Bryce1010模板 http://codeforces.com/problemset/problem/1000/C 题意:问你从[l,r]区间的被多少条线覆盖,列出所有答案. 思路:类似括号匹配的 ...

  4. Codeforces Round #408 (Div. 2) A

    Description Zane the wizard had never loved anyone before, until he fell in love with a girl, whose ...

  5. Android应用的安全隐患*

    转自: http://www.cnblogs.com/chi0591/p/3864747.html Android应用的安全隐患包括三个方面: 代码安全 数据安全 组件安全 代码安全 代码安全主要是指 ...

  6. CoreData修改了数据模型报错 The model used to open the store is incompatible with the one used to create the store

    在iOS 6 – Core Data 应用程序的开发过程中, App启动时出现如下异常信息: reason = “The model used to open the store is incompa ...

  7. 493 Reverse Pairs 翻转对

    给定一个数组 nums ,如果 i < j 且 nums[i] > 2*nums[j] 我们就将 (i, j) 称作一个重要翻转对.你需要返回给定数组中的重要翻转对的数量.示例 1:输入: ...

  8. Oracle历史版本及oracle相关软件下载地址

    网站:https://edelivery.oracle.com/ 可能需要注册个账号!!!(账号注册登录自己折腾下就好了) 下载数据库或者oracle的相关软件的话,如下 选择对应的下载即可!

  9. linux给文件或目录添加apache权限

    系统环境:ubuntu11.10/apache2/php5.3.6 在LAMP环境中,测试一个简单的php文件上传功能时,发现/var/log/apache2/error.log中出现如下php警告: ...

  10. android开发学习 ------- Error:Failed to open zip file.

    我们用Android Studio   Sync Project项目的时候,会出现如下的错误: 解决方案: Project视图下, 这块 https 改为 http 就可以了.