- 原文地址:Part 27: Composition Instead of Inheritance - OOP in Go
- 原文做者:Naveen R
- 譯者:咔嘰咔嘰 轉載請註明出處。
Go 不支持繼承,但它支持組合。組合的通用定義是「放在一塊兒」。組合的一個例子是汽車。汽車由車輪,發動機和各類其餘部件組成。golang
Go 中的組合能夠經過將一種結構類型嵌入到另外一種結構類型中來實現。web
博客文章是一個完美的組合示例。每篇博文都有標題,內容和做者信息。這可使用組合完美地表示。在本教程的後續步驟中,咱們將瞭解如何完成此操做。post
讓咱們先建立一個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
做爲接收者類型,將返回做者的全名。spa
下一步是建立post
結構。code
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
結構,讓咱們經過建立一個博客帖子來完成這個程序。get
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
複製代碼