亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

用復雜合理的模塊擴展計算器(使用動態綁定)

用復雜合理的模塊擴展計算器(使用動態綁定)

Go
嗶嗶one 2022-10-17 09:59:09
我已經制作了可以計算整數和實數的計算器(我用 go 完成了)。然后我想通過添加這些模塊來計算復數和有理數。(它還可以計算類型何時混合)如果我每次(運行時)檢查操作數的類型并處理每種情況,這很容易,但我想用動態綁定來解決它。伙計們,你能告訴我如何解決這個問題的想法嗎
查看完整描述

1 回答

?
寶慕林4294392

TA貢獻2021條經驗 獲得超8個贊

我認為通過動態類型,您可能指的是在例如 C++ 和 Java 中,動態綁定本質上是對可以指向派生類的基類的引用(因為派生類“是”基類)。


有人可能會說,基類定義了派生類變形的接口。如果派生類替換了基類的方法,對基類的引用仍然可以訪問派生類中的那些方法。


基類可以定義一些方法來為其派生類提供一些“基”功能。如果這些類沒有重新定義方法,則可以調用基類的方法。


在 go 中,這兩個概念都存在,但它們完全不同。


Go 有一個明確的interface關鍵字來定義方法簽名但沒有方法。如果任何值具有具有相同簽名的同名方法,則任何值都會隱式滿足該接口。


type LivingBeing interface {

    TakeInEnergy()

    ExpelWaste()

}

接口類型成為代碼中的有效類型。我們可以將接口傳遞給函數,并且在不知道滿足該接口的類型的情況下,可以調用它的方法:


func DoLife(being LivingBeing) {

   being.TakeInEnergy()

   being.ExpelWaste()

}

這是有效的代碼,但不是完整的代碼。與其他語言的基類不同,接口不能定義函數,只能定義它們的簽名。它純粹是一個接口定義。 我們必須將滿足接口的類型與接口本身分開定義。


type Organism struct{}


func (o *Organism) TakeInEnergy() {}


func (o *Organism) ExpelWaste() {}

我們現在有一個organism滿足LivingBeing. 它有點像基類,但如果我們想在它的基礎上構建,我們不能使用子類化,因為 Go 沒有實現它。但是 Go 確實提供了類似的東西,稱為嵌入類型。


在這個例子中,我將定義一個新的有機體 Animal,它ExpelWaste()從 中提取LivingBeing,但定義了自己的TakeInEnergy():


type Animal struct {

    Organism  // the syntax for an embedded type: type but no field name

}


func (a *Animal) TakeInEnergy() {

    fmt.Printf("I am an animal")

}

從該代碼中不明顯的是,因為Animal'sOrganism不是命名字段,所以它的字段和方法可以直接從Animal. 這幾乎就像Animal“是一個”有機體。


然而,它*不是*一個有機體。它是一種不同的類型,將對象嵌入視為語法糖以自動將Organism的字段和方法提升為Animal.


由于 go 是靜態和顯式類型的,DoLife因此不能接受 anOrganism然后傳遞 an Animal:它沒有相同的類型:


/* This does not work.  Animal embeds organism, but *is not* an organism */

func DoLife(being *Organism) {

   being.TakeInEnergy()

   being.ExpelWaste()

}

func main() {

    var a = &Animal{Organism{}}

    DoLife(&Animal{})

}

cannot use &Animal{} (type *Animal) as type *Organism in argument to DoLife


這就是interface存在的原因——因此Organismand Animal(實際上,甚至Plantor ChemotrophBacteria)都可以作為 LivingBeing.

綜上所述,這是我一直在使用的代碼:

package main


import "fmt"


type LivingBeing interface {

    TakeInEnergy()

    ExpelWaste()

}


type Organism struct{}


func (o *Organism) TakeInEnergy() {

}


func (o *Organism) ExpelWaste() {}


type Animal struct {

    Organism

}


func DoLife(being LivingBeing) {

    being.TakeInEnergy()

    being.ExpelWaste()

}


func (a *Animal) TakeInEnergy() {

    fmt.Printf("I am an animal")

}


func main() {

    var a = &Animal{Organism{}}

    DoLife(a)

}


有幾個注意事項:

  1. 從語法上講,如果你想聲明一個嵌入的文字,你必須顯式地提供它的類型。在我的示例Organism中,沒有任何字段,因此無需聲明任何內容,但我仍然將顯式類型留在那里以指向正確的方向。

  2. DoLife可以調用TakeInEnergyLivingBeing 的權利,但Organism的方法不能。他們只看到嵌入的Organism.

func (o *Organism) ExpelWaste() {

    o.getWaste() //this will always be Organism's getWaste, never Animal's

}


func (o *Organism)getWaste() {}


func (a *Animal)getWaste() {

    fmt.Println("Animal waste")

}

同樣,如果您只傳遞嵌入部分,那么它將調用它自己的TakeInEnergy(),而不是Animal; 沒有Animal了!


func main() {

    var a = &Animal{Organism{}}

    DoLife(&a.Organism)

}

總之,

  • 定義顯式interface并在需要“多態”行為的任何地方使用該類型

  • 定義基本類型并將它們嵌入到其他類型中以共享基本功能。

  • 不要期望“基本”類型會“綁定”到“派生”類型的函數。


查看完整回答
反對 回復 2022-10-17
  • 1 回答
  • 0 關注
  • 96 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號