[譯] part 27: golang 的面向對象 -- 組合取代繼承

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)
}
複製代碼

在上面的代碼片斷中,咱們建立了一個包含firstNamelastNamebio字段的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結構具備字段titlecontent。它還嵌入一個匿名字段author。該字段表示post結構由author組成。如今post結構能夠訪問author結構的全部字段和方法。咱們還在 post 結構中添加了details()方法,用於打印做者的titlecontentfullNamebio繼承

每當一個結構嵌入另外一個結構時,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)
}
複製代碼

如今咱們已經準備好了authorpost結構,讓咱們經過建立一個博客帖子來完成這個程序。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()
}
複製代碼

Run in playground編譯器

上面程序中的主要功能是在第 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()
}
複製代碼

Run in playground

在上面的main function中,咱們建立了一個做者author1和三個帖子post1post2post3。最後咱們在第 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  
複製代碼
相關文章
相關標籤/搜索