亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

淺談Go語言多態(tài)的實(shí)現(xiàn)與interface使用

 更新時(shí)間:2021年06月16日 08:42:57   作者:TechFlow2019  
如果大家系統(tǒng)的學(xué)過C++、Java等語言以及面向?qū)ο蟮脑挘嘈艖?yīng)該對(duì)多態(tài)不會(huì)陌生。多態(tài)是面向?qū)ο蠓懂牣?dāng)中經(jīng)常使用并且非常好用的一個(gè)功能,它主要是用在強(qiáng)類型語言當(dāng)中,像是Python這樣的弱類型語言,變量的類型可以隨意變化,也沒有任何限制,其實(shí)區(qū)別不是很大

一、多態(tài)的含義

對(duì)于Java或者是C++而言,我們?cè)谑褂米兞康臅r(shí)候,變量的類型是明確的。但是如果我們希望它可以寬松一點(diǎn),比如說我們用父類指針或引用去調(diào)用方法,但是在執(zhí)行的時(shí)候,能夠根據(jù)子類的類型去執(zhí)行子類當(dāng)中的方法。也就是說實(shí)現(xiàn)我們用相同的調(diào)用方式調(diào)出不同結(jié)果或者是功能的情況,這種情況就叫做多態(tài)。

舉個(gè)非常經(jīng)典的例子,比如說貓、狗和人都是哺乳動(dòng)物。這三個(gè)類都有一個(gè)say方法,大家都知道貓、狗以及人類的say是不一樣的,貓可能是喵喵叫,狗是汪汪叫,人類則是說話。

class Mammal {
    public void say() {
    System.out.println("do nothing")
    }
}


class Cat extends Mammal{
    public void say() {
    System.out.println("meow");
    }
}


class Dog extends Mammal{
    public void say() {
    System.out.println("woof");
    }
}

class Human extends Mammal{
    public void say() {
    System.out.println("speak");
    }
}

這段代碼大家應(yīng)該都不難看懂,這三個(gè)類都是Mammal的子類,假設(shè)這個(gè)時(shí)候我們有一系列實(shí)例,它們都是Mammal的子類的實(shí)例,但是這三種類型都有,我們希望用一個(gè)循環(huán)來一起全都調(diào)用了。雖然我們接收變量的時(shí)候是用的Mammal的父類類型去接收的,但是我們調(diào)用的時(shí)候卻會(huì)獲得各個(gè)子類的運(yùn)行結(jié)果。

比如這樣:

class Main {
    public static void main(String[] args) {
        List<Mammal> mammals = new ArrayList<>();
        mammals.add(new Human());
        mammals.add(new Dog());
        mammals.add(new Cat());
        
        for (Mammal mammal : mammals) {
            mammal.say();
        }
    }
}

不知道大家有沒有g(shù)et到精髓,我們創(chuàng)建了一個(gè)父類的List,將它各個(gè)子類的實(shí)例放入了其中。然后通過了一個(gè)循環(huán)用父類對(duì)象來接收,并且調(diào)用了say方法。我們希望雖然我們用的是父類的引用來調(diào)用的方法,但是它可以自動(dòng)根據(jù)子類的類型調(diào)用對(duì)應(yīng)不同子類當(dāng)中的方法。

也就是說我們得到的結(jié)果應(yīng)該是:

speak

woof

meow

這種功能就是多態(tài),說白了我們可以在父類當(dāng)中定義方法,在子類當(dāng)中創(chuàng)建不同的實(shí)現(xiàn)。但是在調(diào)用的時(shí)候依然還是用父類的引用去調(diào)用,編譯器會(huì)自動(dòng)替我們做好內(nèi)部的映射和轉(zhuǎn)化。

二、抽象類與接口

這樣實(shí)現(xiàn)當(dāng)然是可行的,但其實(shí)有一個(gè)小小的問題,就是Mammal類當(dāng)中的say方法多余了。因?yàn)槲覀兪褂玫闹粫?huì)是它的子類,并不會(huì)用到Mammal這個(gè)父類。所以我們沒必要實(shí)現(xiàn)父類Mammal中的say方法,做一個(gè)標(biāo)記,表示有這么一個(gè)方法,子類實(shí)現(xiàn)的時(shí)候需要實(shí)現(xiàn)它就可以了。

這就是抽象類和抽象方法的來源,我們可以把Mammal做成一個(gè)抽象類,聲明say是一個(gè)抽象方法。抽象類是不能直接創(chuàng)建實(shí)例的,只能創(chuàng)建子類的實(shí)例,并且抽象方法也不用實(shí)現(xiàn),只需要標(biāo)記好參數(shù)和返回就行了。具體的實(shí)現(xiàn)都在子類當(dāng)中進(jìn)行。說白了抽象方法就是一個(gè)標(biāo)記,告訴編譯器凡是繼承了這個(gè)類的子類必須要實(shí)現(xiàn)抽象方法,父類當(dāng)中的方法不能調(diào)用。那抽象類就是含有抽象方法的類。

我們寫出Mammal變成抽象類之后的代碼:

abstract class Mammal {
    abstract void say();
}

很簡(jiǎn)單,因?yàn)槲覀冎恍枰x方法的參數(shù)就可以了,不需要實(shí)現(xiàn)方法的功能,方法的功能在子類當(dāng)中實(shí)現(xiàn)。由于我們標(biāo)記了say這個(gè)方法是一個(gè)抽象方法,凡是繼承了Mammal的子類都必須要實(shí)現(xiàn)這個(gè)方法,否則一定會(huì)報(bào)錯(cuò)。

抽象類其實(shí)是一個(gè)擦邊球,我們可以在抽象類中定義抽象的方法也就是只聲明不實(shí)現(xiàn),也可以在抽象類中實(shí)現(xiàn)具體的方法。在抽象類當(dāng)中非抽象的方法子類的實(shí)例是可以直接調(diào)用的,和子類調(diào)用父類的普通方法一樣。但假如我們不需要父類實(shí)現(xiàn)方法,我們提出提取出來的父類中的所有方法都是抽象的呢?針對(duì)這一種情況,Java當(dāng)中還有一個(gè)概念叫做接口,也就是interface,本質(zhì)上來說interface就是抽象類,只不過是只有抽象方法的抽象類。

所以剛才的Mammal也可以寫成:

interface Mammal {
    void say();
}

把Mammal變成了interface之后,子類的實(shí)現(xiàn)沒什么太大的差別,只不過將extends關(guān)鍵字換成了implements。另外,子類只能繼承一個(gè)抽象類,但是可以實(shí)現(xiàn)多個(gè)接口。早先的Java版本當(dāng)中,interface只能夠定義方法和常量,在Java8以后的版本當(dāng)中,我們也可以在接口當(dāng)中實(shí)現(xiàn)一些默認(rèn)方法和靜態(tài)方法。

接口的好處是很明顯的,我們可以用接口的實(shí)例來調(diào)用所有實(shí)現(xiàn)了這個(gè)接口的類。也就是說接口和它的實(shí)現(xiàn)是一種要寬泛許多的繼承關(guān)系,大大增加了靈活性。

以上雖然全是Java的內(nèi)容,但是講的其實(shí)是面向?qū)ο蟮膬?nèi)容,如果沒有學(xué)過Java的小伙伴可能看起來稍稍有一點(diǎn)點(diǎn)吃力,但總體來說問題不大,沒必要細(xì)扣當(dāng)中的語法細(xì)節(jié),get到核心精髓就可以了。

講這么一大段的目的是為了厘清面向?qū)ο螽?dāng)中的一些概念,以及接口的使用方法和理念,后面才是本文的重頭戲,也就是Go語言當(dāng)中接口的使用以及理念。

三、Golang中的接口

Golang當(dāng)中也有接口,但是它的理念和使用方法和Java稍稍有所不同,它們的使用場(chǎng)景以及實(shí)現(xiàn)的目的是類似的,本質(zhì)上都是為了抽象。通過接口提取出了一些方法,所有繼承了這個(gè)接口的類都必然帶有這些方法,那么我們通過接口獲取這些類的實(shí)例就可以使用了,大大增加了靈活性。

但是Java當(dāng)中的接口有一個(gè)很大的問題就是侵入性,說白了就是會(huì)顛倒供需關(guān)系。舉個(gè)簡(jiǎn)單的例子,假設(shè)你寫了一個(gè)爬蟲從各個(gè)網(wǎng)頁上爬取內(nèi)容。爬蟲爬到的內(nèi)容的類別是很多的,有圖片、有文本還有視頻。假設(shè)你想要抽象出一個(gè)接口來,在這個(gè)接口當(dāng)中定義你規(guī)定的一些提取數(shù)據(jù)的方法。這樣不論獲取到的數(shù)據(jù)的格式是什么,你都可以用這個(gè)接口來調(diào)用。這本身也是接口的使用場(chǎng)景,但問題是處理圖片、文本以及視頻的組件可能是開源或者是第三方的,并不是你開發(fā)的。你定義接口并沒有什么卵用,別人的代碼可不會(huì)繼承這個(gè)接口。

當(dāng)然這也是可以解決的, 比如你可以在這些第三方工具庫外面自己封裝一層,實(shí)現(xiàn)你定義的接口。這樣當(dāng)然是OK的,但是顯然比較麻煩。

Golang當(dāng)中的接口解決了這個(gè)問題,也就是說它完全拿掉了原本弱化的繼承關(guān)系,只要接口中定義的方法能對(duì)應(yīng)的上,那么就可以認(rèn)為這個(gè)類實(shí)現(xiàn)了這個(gè)接口。

我們先來創(chuàng)建一個(gè)interface,當(dāng)然也是通過type關(guān)鍵字:

type Mammal interface {
 Say()
}

我們定義了一個(gè)Mammal的接口,當(dāng)中聲明了一個(gè)Say函數(shù)。也就是說只要是擁有這個(gè)函數(shù)的結(jié)構(gòu)體就可以用這個(gè)接口來接收,我們和剛才一樣,定義Cat、Dog和Human三個(gè)結(jié)構(gòu)體,分別實(shí)現(xiàn)各自的Say方法:

type Dog struct{}

type Cat struct{}

type Human struct{}

func (d Dog) Say() {
 fmt.Println("woof")
}

func (c Cat) Say() {
 fmt.Println("meow")
}

func (h Human) Say() {
 fmt.Println("speak")
}

之后,我們嘗試使用這個(gè)接口來接收各種結(jié)構(gòu)體的對(duì)象,然后調(diào)用它們的Say方法:

func main() {
    var m Mammal
    m = Dog{}
    m.Say()
    m = Cat{}
    m.Say()
    m = Human{}
    m.Say()
}

出來的結(jié)果當(dāng)然和我們預(yù)想的一樣:

四、總結(jié)

今天我們一起聊了面向?qū)ο笾卸鄳B(tài)以及接口的概念,借此進(jìn)一步了解了為什么golang中的接口設(shè)計(jì)非常出色,因?yàn)樗怦盍私涌诤蛯?shí)現(xiàn)類之間的聯(lián)系,使得進(jìn)一步增加了我們編碼的靈活度,解決了供需關(guān)系顛倒的問題。但是世上沒有絕對(duì)的好壞,golang中的接口在方便了我們編碼的同時(shí)也帶來了一些問題,比如說由于沒了接口和實(shí)現(xiàn)類的強(qiáng)綁定,其實(shí)也一定程度上增加了開發(fā)和維護(hù)的成本。

總體來說這是一個(gè)仁者見仁的改動(dòng),有些寫慣了Java的同學(xué)可能會(huì)覺得沒有必要,這是過度解綁,有些人之前深受其害的同學(xué)可能覺得這個(gè)進(jìn)步非常關(guān)鍵。但不論你怎么看,這都不影響我們學(xué)習(xí)它,畢竟學(xué)習(xí)本身是不帶立場(chǎng)的。今天的內(nèi)容當(dāng)中包含一些Java和面向?qū)ο蟮母拍?,只是用來引出后面golang的內(nèi)容,如果存在部分不理解的地方,希望大家抓大放小,理解核心關(guān)鍵就好了,不需要細(xì)扣每一個(gè)細(xì)節(jié)。

以上就是淺談Go語言多態(tài)的實(shí)現(xiàn)與interface使用的詳細(xì)內(nèi)容,更多關(guān)于Go 多態(tài)與interface的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 淺析Golang中閉包的創(chuàng)建與使用

    淺析Golang中閉包的創(chuàng)建與使用

    閉包是包括?Go?在內(nèi)的編程語言的一項(xiàng)強(qiáng)大功能,通過閉包,您可以在函數(shù)中封裝數(shù)據(jù),并通過函數(shù)的返回值訪問這些數(shù)據(jù),本文將介紹Go?中閉包的基礎(chǔ)知識(shí),希望對(duì)大家有所幫助
    2023-11-11
  • Go語言中的內(nèi)存布局詳解

    Go語言中的內(nèi)存布局詳解

    這篇文章主要給大家介紹了Go語言中的內(nèi)存布局,那么本文中將嘗試解釋Go如何在內(nèi)存中構(gòu)建結(jié)構(gòu)體,以及結(jié)構(gòu)體在字節(jié)和比特位方面是什么樣子。 有需要的朋友們可以參考借鑒,感興趣的朋友們下面來跟著小編一起學(xué)習(xí)學(xué)習(xí)吧。
    2016-11-11
  • Golang中正則表達(dá)式語法及相關(guān)示例

    Golang中正則表達(dá)式語法及相關(guān)示例

    正則表達(dá)式是一種用于匹配和操作文本的強(qiáng)大工具,它使用特殊的字符和語法來定義模式,下面這篇文章主要給大家介紹了關(guān)于Golang中正則表達(dá)式語法及相關(guān)示例的相關(guān)資料,需要的朋友可以參考下
    2024-05-05
  • 分析Go語言中CSP并發(fā)模型與Goroutine的基本使用

    分析Go語言中CSP并發(fā)模型與Goroutine的基本使用

    我們都知道并發(fā)是提升資源利用率最基礎(chǔ)的手段,尤其是當(dāng)今大數(shù)據(jù)時(shí)代,流量對(duì)于一家互聯(lián)網(wǎng)企業(yè)的重要性不言而喻。串流顯然是不行的,尤其是對(duì)于web后端這種流量的直接載體。并發(fā)是一定的,問題在于怎么執(zhí)行并發(fā)。常見的并發(fā)方式有三種,分別是多進(jìn)程、多線程和協(xié)程
    2021-06-06
  • Golang 文件操作:刪除指定的文件方式

    Golang 文件操作:刪除指定的文件方式

    這篇文章主要介紹了Golang 文件操作:刪除指定的文件方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • 詳解簡(jiǎn)單高效的Go?struct優(yōu)化

    詳解簡(jiǎn)單高效的Go?struct優(yōu)化

    這篇文章主要為大家介紹了簡(jiǎn)單高效的Go?struct優(yōu)化示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • Go語言字符串拼接方式與性能比較分析

    Go語言字符串拼接方式與性能比較分析

    這篇文章主要為大家介紹了Go語言字符串拼接方式與性能比較示例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • Go語言官方依賴注入工具Wire的使用教程

    Go語言官方依賴注入工具Wire的使用教程

    依賴注入是一種實(shí)現(xiàn)控制反轉(zhuǎn)且用于解決依賴性問題的設(shè)計(jì)模式。Golang?中常用的依賴注入工具主要有?Inject?、Dig?等。但是今天主要介紹的是?Go?團(tuán)隊(duì)開發(fā)的?Wire,一個(gè)編譯期實(shí)現(xiàn)依賴注入的工具,感興趣的可以了解一下
    2022-09-09
  • Golang中優(yōu)秀的消息隊(duì)列NSQ基礎(chǔ)安裝及使用詳解

    Golang中優(yōu)秀的消息隊(duì)列NSQ基礎(chǔ)安裝及使用詳解

    這篇文章主要介紹了Golang中優(yōu)秀的消息隊(duì)列NSQ基礎(chǔ)安裝及使用詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • go語言通過odbc訪問Sql Server數(shù)據(jù)庫的方法

    go語言通過odbc訪問Sql Server數(shù)據(jù)庫的方法

    這篇文章主要介紹了go語言通過odbc訪問Sql Server數(shù)據(jù)庫的方法,實(shí)例分析了Go語言通過odbc連接與查SQL Server詢數(shù)據(jù)庫的技巧,需要的朋友可以參考下
    2015-03-03

最新評(píng)論