[Go 教程系列筆記]組合而不是繼承-Go中的OOP

Go不支持繼承,但它確實支持組合。組合的通用定義是“放在一起”。組合的一個例子是汽車。汽車由車輪,發動機和各種其他部件組成。

通過嵌入結構組成

Go中的組合可以通過將一種結構類型嵌入到另一種結構類型中來實現。

博客文章是一個完美的組合示例。每篇博文都有標題,內容和作者信息。這可以使用組合完美地表示。在本教程的後續步驟中,我們將瞭解如何完成此操作。

<!-- more -->

讓我們首先創建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)
}

在上面的代碼片段中,我們創建了一個author帶字段的結構,firstName,lastName和bio。我們還添加了一個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()方法,用於打印作者的標題,內容,完整名稱和生物。

每當一個struct字段嵌入另一個struct時,Go爲我們提供了訪問嵌入字段的選項,就好像它們是外部結構的一部分一樣。這意味着p.author.fullName()在行中沒有。上面的代碼第 10 行中可以替換爲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()
}

Run in playground

上面程序中的主要功能是在第31行號中創建一個新作者。在第36行創建一個新文章。並嵌入式author。這個程序打印。

Title:  Inheritance in Go  
Content:  Go supports composition instead of inheritance  
Author:  Naveen Ramanathan  
Bio:  Golang Enthusiast 

嵌入 slice 結構

我們可以把這個例子進一步修改,創建使用一個網站有一系列博客文章:)。

讓我們先定義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.go併爲我們的新網站創建一些帖子。

修改主要功能後的完整程序如下所示,

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()
}

Run in playground

在上面的main.go中,我們創建了一個作者author1和三個帖子post1,post2並且post3。最後我們在第63行創建了網站 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  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章