[译] 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  
复制代码
相关文章
相关标签/搜索