1. 程式人生 > >golang教程之組合代替繼承-Go面向物件

golang教程之組合代替繼承-Go面向物件

組合代替繼承-Go面向物件

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

在上面的程式碼片段中,我們建立了一個包含firstNamelastNamebio欄位的author結構。 我們還添加了一個方法fullName()author作為接收者型別,這將返回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 struct可以訪問author

結構的所有欄位和方法。 我們還在post結構中添加了details()方法,用於列印作者的title,content,fullName和bio。

每當一個struct欄位嵌入另一個struct欄位時,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 結構,讓我們通過建立一個部落格文章來完成這個程式。

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行中建立一個新author 。在第36行建立一個新post,嵌入author1。 這個程式列印,

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 []的片段中。

現在讓我們修改主要功能併為我們的新網站建立一些posts。

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

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

在上面的主要功能中,我們建立了一個作者author1和三個帖子post1post2post3。 最後我們在第62行建立了網站。 通過嵌入這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