第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問題,去搜搜看,總會(huì)有你想問的

嘗試使用泛型在 Go 中實(shí)現(xiàn)訪問者模式

嘗試使用泛型在 Go 中實(shí)現(xiàn)訪問者模式

Go
瀟湘沐 2022-12-19 21:10:16
我有以下簡(jiǎn)單的基于泛型的go包,它實(shí)現(xiàn)了 GoF 訪客模式:package patternstype Social interface {    AcceptVisitor(visitor *Visitor)}type Component struct {}func (c *Component) AcceptVisitor(visitor *Visitor) {    visitor.VisitComponent(c)}type Collection[T Social] struct {    Component    items[]T}func (c *Collection[T]) AcceptVisitor(visitor *Visitor) {    visitor.VisitCollection(c) // <- Error Here}type Visitor struct {}func (v *Visitor) VisitComponent(component *Component) {}func (v *Visitor) VisitCollection(collection *Collection[Social]) {    for _, item := range collection.items {        item.AcceptVisitor(v)    }}編譯器給出以下錯(cuò)誤:./patterns.go:20:26: cannot use c (variable of type *Collection[T]) as  type *Collection[Social] in argument to visitor.VisitCollection這對(duì)我來說似乎很奇怪,因?yàn)橥ㄓ妙愋?T 被限制為 Social。我嘗試了幾件事:用接口定義替換了訪問者抽象類型。這導(dǎo)致了社交和訪客界面之間的循環(huán)依賴。從修復(fù)問題的聲明中刪除了泛型,但我們非常需要 Collection 類型的泛型??雌饋韌o應(yīng)該能夠處理這段代碼中的泛型。可能的解決方案:在與@blackgreen 進(jìn)行了非常有幫助的討論之后,我們決定問題出現(xiàn)的原因有以下幾點(diǎn):Go 是(真正)嚴(yán)格類型化的,不允許將傳遞給函數(shù)的參數(shù)“縮小”為原始類型的子集,即使編譯器仍然可以證明它是安全的。Go 是否應(yīng)該允許縮小范圍是有爭(zhēng)議的。Go 不允許對(duì)方法進(jìn)行泛型約束,因?yàn)榧s束可能會(huì)與與方法關(guān)聯(lián)的結(jié)構(gòu)上的泛型約束發(fā)生沖突。Go,沒錯(cuò),不允許循環(huán)依賴。我們可以將訪問者模式的所有依賴項(xiàng)抽象為接口,但隨后將具有該模式的“雙重分派”方面所需的循環(huán)依賴項(xiàng)。為了繞過這些項(xiàng)目,并仍然獲得訪問者模式的好處,我們可以將訪問者結(jié)構(gòu)中的 VisitXYZ() 方法更改為(可能是通用的)函數(shù),每個(gè)函數(shù)都將 *Visitor 參數(shù)作為函數(shù)的第一個(gè)參數(shù)和被訪問的對(duì)象作為第二個(gè)參數(shù)。我在 Go Playground 中發(fā)布了這個(gè)解決方案:https ://go.dev/play/p/vV7v61teFbj注意:即使這個(gè)可能的解決方案看起來確實(shí)可以解決問題,但實(shí)際上并沒有。如果您考慮編寫幾種不同類型的訪問者(一種用于漂亮打印,一種用于復(fù)制,一種用于排序等),您很快就會(huì)意識(shí)到,由于 VisitXYZ() 函數(shù)不是方法,因此您不能為每個(gè)函數(shù)擁有多個(gè)版本每個(gè)訪客類型。最后,Visitor 模式確實(shí)需要 Social 接口和 Visitor 接口之間的循環(huán)依賴這一事實(shí)注定了 Go 的失敗。我將關(guān)閉這篇文章,但會(huì)留下分析,這樣其他人就不需要重復(fù)了。
查看完整描述

1 回答

?
尚方寶劍之說

TA貢獻(xiàn)1788條經(jīng)驗(yàn) 獲得超4個(gè)贊

我得出的結(jié)論是泛型讓這種模式變得更糟。通過參數(shù)化Collection結(jié)構(gòu),您強(qiáng)制items []T擁有相同的元素。使用普通接口,您可以進(jìn)行動(dòng)態(tài)分派,從而允許items包含不同的實(shí)現(xiàn)。僅此一項(xiàng)就應(yīng)該是充分的理由。


這是一個(gè)沒有泛型的最小實(shí)現(xiàn),改編自一些 Java 示例(可運(yùn)行代碼):


主要接口:


type Visitor func(Element)


type Element interface {

    Accept(Visitor)

}

實(shí)施者:


type Foo struct{}


func (f Foo) Accept(visitor Visitor) {

    visitor(f)

}

容器:


type List struct {

    elements []Element

}


func (l *List) Accept(visitor Visitor) {

    for _, e := range l.elements {

        e.Accept(visitor)

    }

    visitor(l)

}

訪客本身,作為常規(guī)功能。在這里您可以自由定義任何功能。由于是無類型的,您可以直接將其作為Visitor參數(shù)傳遞:


func doVisitor(v Element) {

    switch v.(type) {

    case *List:

        fmt.Println("visiting list")

    case Foo:

        fmt.Println("visiting foo")

    case Bar:

        fmt.Println("visiting bar")

    }

}


查看完整回答
反對(duì) 回復(fù) 2022-12-19
  • 1 回答
  • 0 關(guān)注
  • 130 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)