- 原文地址:Part 27: Composition Instead of Inheritance - OOP in Go
- 原文作者:Naveen R
- 譯者:咔嘰咔嘰 轉載請註明出處。
Go 不支援繼承,但它支援組合。組合的通用定義是“放在一起”。組合的一個例子是汽車。汽車由車輪,發動機和各種其他部件組成。
通過嵌入結構組合
Go 中的組合可以通過將一種結構型別嵌入到另一種結構型別中來實現。
部落格文章是一個完美的組合示例。每篇博文都有標題,內容和作者資訊。這可以使用組合完美地表示。在本教程的後續步驟中,我們將瞭解如何完成此操作。
讓我們先建立一個author
結構
package main
import (
"fmt"
)
type author struct {
firstName string
lastName string
bio string
}
func (a author) fullName() string {
return fmt.Sprintf("%s %s", a.firstName, a.lastName)
}
複製程式碼
在上面的程式碼片段中,我們建立了一個包含firstName
,lastName
和bio
欄位的author
結構。我們還新增了一個方法fullName()
,author
作為接收者型別,將返回作者的全名。
下一步是建立post
結構。
type post struct {
title string
content string
author
}
func (p post) details() {
fmt.Println("Title: ", p.title)
fmt.Println("Content: ", p.content)
fmt.Println("Author: ", p.author.fullName())
fmt.Println("Bio: ", p.author.bio)
}
複製程式碼
post
結構具有欄位title
,content
。它還嵌入一個匿名欄位author
。該欄位表示post
結構由author
組成。現在post
結構可以訪問author
結構的所有欄位和方法。我們還在 post 結構中新增了details()
方法,用於列印作者的title
,content
,fullName
和bio
。
每當一個結構嵌入另一個結構時,Go 為我們提供了訪問嵌入欄位的選項,就好像它們是外部結構的一部分一樣。這意味著p.author.fullName()
可以用p.fullName()
替換。因此,details()
方法可以重寫如下,
func (p post) details() {
fmt.Println("Title: ", p.title)
fmt.Println("Content: ", p.content)
fmt.Println("Author: ", p.fullName())
fmt.Println("Bio: ", p.bio)
}
複製程式碼
現在我們已經準備好了author
和post
結構,讓我們通過建立一個部落格帖子來完成這個程式。
package main
import (
"fmt"
)
type author struct {
firstName string
lastName string
bio string
}
func (a author) fullName() string {
return fmt.Sprintf("%s %s", a.firstName, a.lastName)
}
type post struct {
title string
content string
author
}
func (p post) details() {
fmt.Println("Title: ", p.title)
fmt.Println("Content: ", p.content)
fmt.Println("Author: ", p.fullName())
fmt.Println("Bio: ", p.bio)
}
func main() {
author1 := author{
"Naveen",
"Ramanathan",
"Golang Enthusiast",
}
post1 := post{
"Inheritance in Go",
"Go supports composition instead of inheritance",
author1,
}
post1.details()
}
複製程式碼
上面程式中的主要功能是在第 31 行中建立一個新的作者,在第 36 行嵌入該作者然後建立一個新帖子。這個程式列印,
Title: Inheritance in Go
Content: Go supports composition instead of inheritance
Author: Naveen Ramanathan
Bio: Golang Enthusiast
複製程式碼
嵌入結構切片
我們可以進一步採用這個例子,並使用一些部落格帖子建立一個網站:)。
讓我們先定義website
結構。我們將在現有程式的基礎上新增以下程式碼並執行它。
type website struct {
[]post
}
func (w website) contents() {
fmt.Println("Contents of Website\n")
for _, v := range w.posts {
v.details()
fmt.Println()
}
}
複製程式碼
在新增上面的程式碼後,執行時編譯器會報以下錯誤,
main.go:31:9: syntax error: unexpected [, expecting field name or embedded type
複製程式碼
此錯誤指向結構[]post
的嵌入切片。原因是不能匿名嵌入一個切片。欄位名稱是必需的。所以讓我們修復這個錯誤。
type website struct {
posts []post
}
複製程式碼
我已將欄位名稱posts
新增到[]post
的切片中。
現在讓我們修改main function
併為我們的新網站建立一些帖子。
修改後的完整程式如下,
package main
import (
"fmt"
)
type author struct {
firstName string
lastName string
bio string
}
func (a author) fullName() string {
return fmt.Sprintf("%s %s", a.firstName, a.lastName)
}
type post struct {
title string
content string
author
}
func (p post) details() {
fmt.Println("Title: ", p.title)
fmt.Println("Content: ", p.content)
fmt.Println("Author: ", p.fullName())
fmt.Println("Bio: ", p.bio)
}
type website struct {
posts []post
}
func (w website) contents() {
fmt.Println("Contents of Website\n")
for _, v := range w.posts {
v.details()
fmt.Println()
}
}
func main() {
author1 := author{
"Naveen",
"Ramanathan",
"Golang Enthusiast",
}
post1 := post{
"Inheritance in Go",
"Go supports composition instead of inheritance",
author1,
}
post2 := post{
"Struct instead of Classes in Go",
"Go does not support classes but methods can be added to structs",
author1,
}
post3 := post{
"Concurrency",
"Go is a concurrent language and not a parallel one",
author1,
}
w := website{
posts: []post{post1, post2, post3},
}
w.contents()
}
複製程式碼
在上面的main function
中,我們建立了一個作者author1
和三個帖子post1
,post2
和post3
。最後我們在第 62 行建立了網站w
。 通過嵌入這 3 個帖子並在下一行顯示內容。
程式輸出,
Contents of Website
Title: Inheritance in Go
Content: Go supports composition instead of inheritance
Author: Naveen Ramanathan
Bio: Golang Enthusiast
Title: Struct instead of Classes in Go
Content: Go does not support classes but methods can be added to structs
Author: Naveen Ramanathan
Bio: Golang Enthusiast
Title: Concurrency
Content: Go is a concurrent language and not a parallel one
Author: Naveen Ramanathan
Bio: Golang Enthusiast
複製程式碼