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

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

Go接口返回類型

Go接口返回類型

Go
aluckdog 2023-05-15 14:54:57
我有一個這樣的界面:type ViewInterface interface{    Init() View}type View struct{    Width  int    Height int}所以我從 View 創建了一個新類型type MainView Viewfunc (m MainView) Init() MainView{ return MainView{   Width:10,   Height:10, }}然后我將 MainView 傳遞給以下方法:func Render(views ...ViewInterface){  for _, view := range views {     v := view.Init()  }}func main() {  Render(MainView{})}但我收到此錯誤:不能使用 MainView 文字(MainView 類型)作為 Render 參數中的 ViewInterface 類型:MainView 沒有實現 ViewInterface(Init 方法的類型錯誤)有 Init() MainView想要 Init() View為什么MianView不一樣View?解決這個問題的正確方法是什么?
查看完整描述

2 回答

?
慕碼人2483693

TA貢獻1860條經驗 獲得超9個贊

因為type MainView View是“定義的類型”并且“不同于任何其他類型,包括創建它的類型。?”。

相反,您可以使用類型別名。type MainView = View.


ViewInterface但真正的問題是和的設計Init()。

Init()寫得像一個類方法。Go 沒有類方法(或者,嚴格來說,類)。您創建結構并在其上調用方法。簡單的初始化可以馬上完成。

view?:=?View{?Width:?10,?Height:?10?}

如果您想定義一個方法來一致地初始化值,它將作用于現有結構并且不返回任何內容。

type ViewInterface interface{

? ? Init()

}


type View struct{

? ? Width? int

? ? Height int

}


func (v *View) Init() {

? ? v.Width = 10

? ? v.Height = 10

}


view := View{}

view.Init()

然后MainView還可以定義Init().


type MainView struct {

? ? X int

? ? Y int

}


type (mv *MainView) Init() {

? ? mv.X = 23

? ? mv.Y = 42

}

因為Init()需要一個指針,為了滿足ViewInterface你必須傳入指針。


func main() {

? ? view := View{}

? ? mv := MainView{}

? ? Render(&view, &mv)

}

但是Render()初始化對象到底在做什么呢?那應該已經完成了。應該是渲染。接口應該是關于通用功能的,而不考慮它是如何實現的。實現 ViewInterface 的東西應該已經初始化了。


相反,您可能會說ViewInterface必須有一個Render方法。


type ViewInterface interface{

? ? Render()

}

然后,View只要MainView它們實現,就可以按照您喜歡的方式進行結構化Render()。


func (v View) Render() {

? ? fmt.Println("View!")

? ? fmt.Println(v)

}


func (mv MainView) Render() {

? ? fmt.Println("MainView!")

? ? fmt.Println(mv)

}

然后 aRender()可以列出實現ViewInterface和調用Render()它們中的每一個的事物。


func Render(views ...ViewInterface){

? for _, view := range views {

? ? ?view.Render()

? }

}

在傳入之前初始化它們?,F在不需要傳遞指針。


func main() {

? ? view := View{}

? ? view.Init()

? ? mv := MainView{}

? ? mv.Init()

? ? Render(view, mv)

}

最后,Markus 在評論中建議使用包來獲取類方法之類的東西。


# viewtest/main.go

package main


import(

? ? "log"

? ? "viewtest/view"

)


func main() {

? ? v := view.New()

? ? log.Printf("%#v", v)

}



# viewtest/view/view.go

package view


type View struct {

? ? Width? int

? ? Height int

}


func New() View {

? ? return View{Width: 10, Height: 10}

}

Go 包需要一點時間來適應,Go 對你的項目必須如何構建有堅定的想法。


查看完整回答
反對 回復 2023-05-15
?
呼如林

TA貢獻1798條經驗 獲得超3個贊

與 Java 和 C# 等主流語言相比,Go 具有不同的繼承模型。


為什么MianView 和View 不一樣?


因為它們的定義不同。


InitMainView返回的函數MainView,而接口需要返回View。


方法簽名Init看起來很奇怪,它需要結構實例,因為它是結構方法并返回相同結構類型的新實例。


嘗試圍繞結構的邏輯而不是結構/生命周期來設計界面:


type ViewInterface interface{

    Render()

}


type MainView View


func (m MainView) Render() {

  // do something

}


type AnotherView


func (m AnotherView) Render() {

  // do something else

}


func Render(views ...ViewInterface){

  for _, view := range views {

     view.Render()

  }

}


查看完整回答
反對 回復 2023-05-15
  • 2 回答
  • 0 關注
  • 190 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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