go语言基础 -- 面向对象 -- 接口与多态

本文介绍了Go语言中接口的声明、实现方式,强调了接口在方法定义、多态性以及在排序等场景的应用。通过实例展示了如何通过接口实现多态,并与继承进行了对比分析。
摘要由CSDN通过智能技术生成

接口定义与基本使用 - interface

go语言中,接口类型可以定义一组方法,不需要在接口定义中实现方法,并且interface中不能含有变量,如果某个自定义类型要使用时再实现接口的方法。
golang中的接口不需要显式地实现,只要一个类型实现了接口所有的方法,那么这个类型就实现了这个接口
接口的声明与实现

package main
import (
    "fmt"
)
// 声明一个接口
type Usb interface {
    // 声明两个没有实现的方法
    Start()
    Stop()
}

type Phone struct {

}
// 让Phone实现Usb接口的方法
// 实现一个接口,就是实现接口的所有方法
func (p Phone) Start() {
    fmt.Println("phone start")
}
func (p Phone) Stop() {
    fmt.Println("phone stop"))
}

type Camera struct {

}
func (c Camera) Start() {
    fmt.Println("camera start")
}
func (c Camera) Stop() {
    fmt.Println("camera stop")
}

type Computer {

}
// Working接收一个Usb接口的参数
func (c Computer) Working(usb Usb) {
    usb.start()
    usb.stop()
}
func main() {
    computer := Computer{}
    phone := Phone{}
    camera := Camera{}
    // 调用phone的方法
    computer.Working(phone)
    // 调用camera的方法
    computer.Working(camera)
}

接口应用场景

定义好接口后,可方便地分配好各个接口的实现工作

接口使用的注意事项

  1. 接口不能用来创建对象,但可以用来指向一个实现了该接口的对象
type Student struct{
    Name string
}
type A interface {
    Say()
}
func (stu Student) Say() {
    fmt.Println(stu.Name)
}
func main() {
    stu := Student{"John"}
    // 可以用接口指向一个定义好的对象,然后用接口调用对象的方法
    a A = stu
    a.Say()
}
  1. 只要是自定义类型,都可以实现接口
  2. 一个自定义类型可以实现多个接口。如果将一个类型变量赋值给不同的接口,那么就能使用不同的接口来调用该类型的方法。
  3. 一个接口可以继承自其他多个接口,这时如果要实现该接口,需要实现其继承的所有接口,继承的方式也类似结构体的继承,定义匿名接口即可,下例:
type Ai interface {
    SayA()
}
type Bi interface {
    SayB()
}
type Ci interface {
    Ai
    Bi
    SayC()
}
  1. interface类型默认是指针,如果没初始化就使用,会输出nil
  2. 空接口没有实现任何方法,所有类型都实现了空接口,我们可以把任意类型(包括基础数据类型)的变量赋值给空接口;
type T interface{
}
func main() {
    var stu Student
    var t T = stu
}
  1. 接口的继承不允许出现相同的方法名
  2. 在将变量赋值给接口时,严格区分指针类型和值类型
type Cap interface{
    Say()
}
type Stu struct{
}
func (this *Stu) Say() {
    fmt.Println("stu say")
}
func main() {
    var stu Stu = Stu{}
    cap interface = &stu // 这里不能写成stu
}

接口的最佳实践案例

实现对hero结构体切片的排序,我们可以用官方库里面的Sort函数,这个函数接收Interface参数,只需要实现Interface的三个方法,即可对对应的接口变量进行排序:
在这里插入图片描述

package main
import(
    "fmt"
    "sort"
)

type Hero struct {
    Name string
    Age int
}
// 声明一个Hero切片类型
type HeroSlice []Hero
// 实现Interface的三个方法
func (hs HeroSlice) Len() int {
    return len(hs)
}
// 若i下标变量大于j下标变量成立被返回,则降序,否则升序
func (hs HeroSlice) Less(i int, j int) bool {
    return hs[i].Age > hs[j].Age
}
func (hs HeroSlice) Swap(i, j int) {
    //temp := hs[i]
    //hs[i] = hs[j]
    //hs[j] = temp
    // go中可以直接这样写交换
    hs[i], hs[j] = hs[j], hs[i]
}
func main() {
    var heros = HeroSlice
    // 初始化heros...
    // 排序
    sort.Sort(heros)
}

接口与继承的对比总结

  1. 当我们不想破坏继承关系,但想对某个自定义类型扩展功能,那么就可以通过接口来实现,实现接口可以看做对继承的一种补充
  2. 当两个不同的结构体需要实现同样的方法的时候,用接口比在原结构体上分别实现方法会更加灵活
  3. 继承的价值更多在于复用和可维护,接口的价值在于规范设计,至于规范实现可交由其他自定义类型实现

go语言中的多态

所谓多态,指的是变量的多种形态,像c/c++语言中允许父类的指针指向子类的对象,在go里面,多态是通过接口来实现的,通过统一的接口来调用不同的实现,接口变量就呈现了多种形态。如Usb接口,可以接收手机变量和相机变量,就体现了usb接口的多态特征(根据传入的变量具体类型来决定调用什么方法)

接口的多态体现

  1. 多态参数,也即同一个接口作为参数,但可以根据具体传入的变量类型来决定使用的方法
  2. 多态数组,如定义一个Usb接口,可以存放phone结构体对象和Camera结构体对象,这就允许数组存放多种类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值