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("断言失败")
    }
    

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

  • 相关阅读:
    209. Minimum Size Subarray Sum
    208. Implement Trie (Prefix Tree)
    207. Course Schedule
    206. Reverse Linked List
    205. Isomorphic Strings
    204. Count Primes
    203. Remove Linked List Elements
    201. Bitwise AND of Numbers Range
    199. Binary Tree Right Side View
    ArcGIS API for JavaScript 4.2学习笔记[8] 2D与3D视图同步
  • 原文地址:https://www.cnblogs.com/RandyField/p/14046707.html
Copyright © 2011-2022 走看看