前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Golang】快速复习指南QuickReview(七)——interface

【Golang】快速复习指南QuickReview(七)——interface

作者头像
DDGarfield
发布2022-06-23 19:07:15
2820
发布2022-06-23 19:07:15
举报
文章被收录于专栏:加菲的博客加菲的博客

在C#中,接口是实现多态的方式之一,但是接口更侧重对象的能力,是一种规范。如果继承了接口,就必须按照接口的要求去实现这个接口。接口与接口之间是可以有继承。而golang中的接口,是一组方法的集合体,duck-type programming的一种体现。

如果有一种动物能够像鸭子那样行走,叫的也像鸭子,那么我们认为这就是鸭子。

1.C#的接口

前文提到,C#的接口侧重于能力,好的接口功能(能力)单一,接口能继承接口,类能继承多个接口(多种能力),如果继承了接口,就必须全部实现。

1.1 接口定义

接口中可以定义属性,索引器,甚至事件,接下来我们定义一个运动员IPlayer的接口:

代码语言:javascript
复制
public interface IPlayer
{
    //接口可以定义属性
    string Name { get; set; }
    double Height { get; set; }
    int Age { get; set; }
    
    //运动
    void PlaySport();
}

1.2 接口继承接口

再定义一个职业篮球运动员接口IBasketPlayer

  • 首先职业篮球运动员也是一个运动员,所以继承运动员接口IPlayer
  • 其次,不管是哪个联赛的职业运动员,除了有一些通用的技术能力,都会面临转会事件TransferEvent
代码语言:javascript
复制
public interface IBasketPlayer: IPlayer
{
        //臂展
        double Wingspan { get; }

        //垂直摸高
        double Verticalreach { get; }

        //垂直跳跃
        double Verticalleap { get; }

        //索引器  为了演示,强行加一个索引器
        string this[string index]
        {
            get; set;
        }

        event EventHandler TransferEvent;


        //扣篮
        void Dunk();
        //传球
        void Pass();
        void Dribble();
        //3分球
        void ThreePointShot();
        //中远距离
        void TwoPointShot();
        //空接
        void AlleyOop();
        //篮板
        void Backboard();
}

1.3 实现接口

  • 定义一个NBA球员 NBAPlayer
代码语言:javascript
复制
public class NBAPlayer : IBasketPlayer
{
    //索引器
    public string this[string index] { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
    
    //臂展
    public double Wingspan => throw new NotImplementedException();
    
    //垂直摸高
    public double Verticalreach => throw new NotImplementedException();
    
    //垂直起跳
    public double Verticalleap => throw new NotImplementedException();
    
    //姓名
    public string Name { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
    
    //身高
    public double Height { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
    
    //年龄
    public int Age { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }

    public event EventHandler TransferEvent;

    public void AlleyOop()
    {
        throw new NotImplementedException();
    }

    public void Backboard()
    {
        throw new NotImplementedException();
    }

    public void Dribble()
    {
        throw new NotImplementedException();
    }

    public void Dunk()
    {
        throw new NotImplementedException();
    }

    public void Pass()
    {
        throw new NotImplementedException();
    }

    public void PlaySport()
    {
        throw new NotImplementedException();
    }

    public void ThreePointShot()
    {
        throw new NotImplementedException();
    }

    public void TwoPointShot()
    {
        throw new NotImplementedException();
    }
}
  • 在定义一个CBA球员 实现接口CBAPlayer
代码语言:javascript
复制
public class CBAPlayer : IBasketPlayer
{
    //索引器
    public string this[string index] { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
    
    //臂展
    public double Wingspan => throw new NotImplementedException();
    
    //锤子摸高
    public double Verticalreach => throw new NotImplementedException();
    
    //垂直起跳
    public double Verticalleap => throw new NotImplementedException();
    
    //姓名
    public string Name { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
    
    //身高
    public double Height { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
    
    //年龄
    public int Age { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }

    //转会事件
    public event EventHandler TransferEvent;

    public void AlleyOop()
    {
        throw new NotImplementedException();
    }

    public void Backboard()
    {
        throw new NotImplementedException();
    }

    public void Dribbl()
    {
        throw new NotImplementedException();
    }

    public void Dunk()
    {
        throw new NotImplementedException();
    }

    public void Pass()
    {
        throw new NotImplementedException();
    }

    public void PlaySport()
    {
        throw new NotImplementedException();
    }

    public void ThreePointShot()
    {
        throw new NotImplementedException();
    }

    public void TwoPointShot()
    {
        throw new NotImplementedException();
    }
}

1.4 实现多个接口

NBA很多黑人球员,不但会打篮球,还会说唱,(黑人,人均会跳舞,会说唱,^_^),比较有名的有艾弗森,阿泰斯特,利拉德,尤其是艾弗森Allen Iverson,很多音乐平台都能搜到,但是CBA球员就不一定会说唱,所以继续定义一个说唱接口 IRapper

代码语言:javascript
复制
public interface IRapper
{
    void Rapper();
}
代码语言:javascript
复制
public class NBAPlayer : IBasketPlayer,IRapper
{
    //索引器
    public string this[string index] { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
    
    //臂展
    public double Wingspan => throw new NotImplementedException();
    
    //锤子摸高
    public double Verticalreach => throw new NotImplementedException();
    
    //垂直起跳
    public double Verticalleap => throw new NotImplementedException();
    
    //姓名
    public string Name { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
    
    //身高
    public double Height { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
    
    //年龄
    public int Age { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }

    //转会
    public event EventHandler TransferEvent;
    
    //会说唱
    public void Rapper()
    {
        throw new NotImplementedException();
    }
    

    public void AlleyOop()
    {
        throw new NotImplementedException();
    }

    public void Backboard()
    {
        throw new NotImplementedException();
    }

    public void Dribbl()
    {
        throw new NotImplementedException();
    }

    public void Dunk()
    {
        throw new NotImplementedException();
    }

    public void Pass()
    {
        throw new NotImplementedException();
    }

    public void PlaySport()
    {
        throw new NotImplementedException();
    }

    public void ThreePointShot()
    {
        throw new NotImplementedException();
    }

    public void TwoPointShot()
    {
        throw new NotImplementedException();
    }
}

2.Golang的接口

C#的接口可以说一种规范,它可以包含数据的规范,比如属性,事件,索引器,也可以包含行为(方法)的规范,但是Golang有所不同:Golang不关心数据,只关心行为(方法)。

2.1 接口定义

接口是一种类型,抽象类型,就像定义struct一样定义:

代码语言:javascript
复制
type Player interface {
 PlaySport()
}

2.2 实现接口

一个对象(能作为方法的接收者)只要实现了接口中定义的方法,那么就算实现了这个接口。

代码语言:javascript
复制
func main(){
    var player Player = &NBAPlayer{
        Name: "James",
    }

 player.PlaySport()
}
type Player interface {
 PlaySport()
}
type NBAPlayer struct {
 Name          string
 Height        float32
 Age           int8
 Wingspan      float32
 Verticalreach float32
 Verticalleap  float32
}
//指针接收者实现接口
func (p *NBAPlayer) PlaySport() {
 fmt.Println(p.Name, "从事的运动项目是打篮球")
}
代码语言:javascript
复制
James 从事的运动项目是打篮球

ps:如果是上面的代码采用值接收者func (p NBAPlayer) PlaySport(),无论是结构体还是结构体指针都可以赋值给接口变量,因为Go语言中有对指针类型变量求值的语法糖,结构体指针内部会自动求值*struct。如果是上面代码那样采用指针接收者,那么接口变量就必须传指针。这个问题如果不熟练,会在实际编码中一次次被编译器打脸。

2.3 实现多个接口

一个NBA球员既要实现Player接口,又要实现Rapper接口:

代码语言:javascript
复制
func main(){
    var player Player = &NBAPlayer{
        Name: "James",
    }
 var rapper Rapper = &NBAPlayer{
  Name: "James",
 }

 player.PlaySport()
 rapper.Rapper()
}
type Rapper interface {
 Rapper()
}
type Player interface {
 PlaySport()
}
type NBAPlayer struct {
 Name          string
 Height        float32
 Age           int8
 Wingspan      float32
 Verticalreach float32
 Verticalleap  float32
}
//指针接收者实现接口
func (p *NBAPlayer) PlaySport() {
 fmt.Println(p.Name, "从事的运动项目是打篮球")
}
func (p *NBAPlayer) Rapper() {
 fmt.Println(p.Name, "还会说唱")
}
代码语言:javascript
复制
James 从事的运动项目是打篮球
James 还会说唱

2.4 嵌套接口

接口BasketPlayer嵌套接口Player,Rapper,这个就类似于C#接口可以继承接口。

代码语言:javascript
复制
func main(){
 var nbaplayer BasketPlayer = &NBAPlayer{
  Name: "Allen Iverson",
 }
 nbaer.PlaySport()
 nbaer.Rapper()
    nbaer.Dunk()
}
type BasketPlayer interface {
 Player
 Rapper
    Dunk()
}
func (p *NBAPlayer) PlaySport() {
 fmt.Println(p.Name, "从事的运动项目是打篮球")
}
func (p *NBAPlayer) Rapper() {
 fmt.Println(p.Name, "还会说唱")
}
func (p *NBAPlayer) Dunk() {
 fmt.Println(p.Name, "会扣篮")
}
代码语言:javascript
复制
Allen Iverson 从事的运动项目是打篮球
Allen Iverson 还会说唱
Allen Iverson 会扣篮

2.5* 空接口

空接口是指没有定义任何方法的接口。**因此任何类型都实现了空接口。**套用周星驰电影的台词,”其实根本没有什么空接口,或许一切都是都是空接口“,空接口类型的变量可以存储任意类型的变量。

2.5.1 空接口切片
  • 看一下fmt包的Println方法,参数就是一个空接口的切片
代码语言:javascript
复制
func Println(a ...interface{}) (n int, err error) {
 return Fprintln(os.Stdout, a...)
}
2.5.2 保存任意值的map
  • 我们定义map make(map[TKey]TValue),当TValue换成interface{}空接口时,这时候的mapvalue就不再是单一的类型,而是可以为任意类型。
代码语言:javascript
复制
 var player = make(map[string]interface{})
 player["name"] = "LeBron James"
 player["age"] = 36
2.5.3 类型断言

类型断言主要用于判断空接口中的值,因为空接代表任意类型。x.(T)

代码语言:javascript
复制
var x interface{}
x = "randyfield"
v, ok := x.(string)
if ok {
    fmt.Println(v)
} else {
    fmt.Println("断言失败")
}

关于接口,不要为了接口而写接口,会增加不必要的抽象,导致不必要的运行时损耗。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-02-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 加菲的博客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.C#的接口
    • 1.1 接口定义
      • 1.2 接口继承接口
        • 1.3 实现接口
          • 1.4 实现多个接口
          • 2.Golang的接口
            • 2.1 接口定义
              • 2.2 实现接口
                • 2.3 实现多个接口
                  • 2.4 嵌套接口
                    • 2.5* 空接口
                      • 2.5.1 空接口切片
                      • 2.5.2 保存任意值的map
                      • 2.5.3 类型断言
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档