zoukankan      html  css  js  c++  java
  • 【Golang】快速复习指南QuickReview(七)——接口interface

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

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

    1.C#的接口

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

    1.1 接口定义

    接下来我们定义一个运动员IPlayer的接口:

    public interface IPlayer
    {
        //接口可以定义属性
        string Name { get; set; }
        double Height { get; set; }
        int Age { get; set; }
        
        //运动
        void PlaySport();
    }
    

    1.2 接口继承接口

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

    • 首先职业篮球运动员也是一个运动员,所以继承运动员接口IPlayer
    • 其次,不管是哪个联赛的职业运动员,除了有一些通用的技术能力,都会面临转会事件TransferEvent
    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
    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
    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

    public interface IRapper
    {
        void Rapper();
    }
    
    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一样定义:

    type Player interface {
    	PlaySport()
    }
    

    2.2 实现接口

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

    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, "从事的运动项目是打篮球")
    }
    
    James 从事的运动项目是打篮球
    

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

    2.3 实现多个接口

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

    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, "还会说唱")
    }
    
    James 从事的运动项目是打篮球
    James 还会说唱
    

    2.4 嵌套接口

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

    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, "会扣篮")
    }
    
    Allen Iverson 从事的运动项目是打篮球
    Allen Iverson 还会说唱
    Allen Iverson 会扣篮
    

    2.5* 空接口

    空接口是指没有定义任何方法的接口。因此任何类型都实现了空接口。”或许一切都是都是空接口“,空接口类型的变量可以存储任意类型的变量。

    2.5.1 空接口切片

    • 看一下fmt包的Println方法,参数就是一个空接口的切片
    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就不再是单一的类型,而是可以为任意类型。
    	var player = make(map[string]interface{})
    	player["name"] = "LeBron James"
    	player["age"] = 36
    

    2.5.3 类型断言

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

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

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

  • 相关阅读:
    view上面 长view时候要设置其frame的,
    controller.allowsEditing = NO;神医,
    怎样计算,遗留,
    编码,一点阅读(转:阮一峰的网络日志),
    原来 ascll是对英文系统的编码,
    CoreGraphics 画图,(转燕羽天空)
    Core Graphics,
    计算数据类型占有 字节的长度,
    浅谈Promise(一)
    原生js实现表格内容增删改
  • 原文地址:https://www.cnblogs.com/RandyField/p/14046707.html
Copyright © 2011-2022 走看看