天天看點

【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{}

    空接口時,這時候的

    map

    value

    就不再是單一的類型,而是可以為任意類型。
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("斷言失敗")
}
           
關于接口,不要為了接口而寫接口,會增加不必要的抽象,導緻不必要的運作時損耗。

再次強調:這個系列并不是教程,如果想系統的學習,部落客可推薦學習資源。

作者:Garfield

同步更新至個人部落格:http://www.randyfield.cn/

本文版權歸作者所有,未經許可禁止轉載,否則保留追究法律責任的權利,若有需要請聯系[email protected]

微信公衆号

掃描下方二維碼關注個人微信公衆号,實時擷取更多幹貨

【Golang】快速複習指南QuickReview(七)——接口interface

同步更新至:http://www.randyfield.cn/

出處:http://www.cnblogs.com/RandyField/

本文版權歸作者和部落格園共有,未經許可禁止轉載,否則保留追究法律責任的權利,若有需要請聯系[email protected].