迹忆客 专注技术分享

当前位置:主页 > 学无止境 > 编程语言 >

Go 面向对象 - 组合 替代 继承

作者:迹忆客 最近更新:2021/10/12 浏览次数:

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类型的参数,它返回作者的全名。

下一步是创建 blogPost 结构体。

type blogPost struct {  
    title     string
    content   string
    author
}

func (b blogPost) details() {  
    fmt.Println("Title: ", b.title)
    fmt.Println("Content: ", b.content)
    fmt.Println("Author: ", b.author.fullName())
    fmt.Println("Bio: ", b.author.bio)
}

blogPost 结构体具有 titlecontent 字段。 它还具有嵌入式匿名字段 author。 该字段表示 blogPost 结构体由 author 组成。 现在 blogPost 结构可以访问 author 结构的所有字段和方法。 我们还向 blogPost 结构添加了 details() 方法,该方法打印了作者的标题、内容、全名和简介。

每当一个结构体字段嵌入到另一个结构体中时,Go 都为我们提供了访问嵌入字段的选项,就好像它们是外部结构体的一部分一样。 这意味着 p.author.fullName() 可以用 p.fullName() 替换。 因此 details() 方法可以重写如下,

func (p blogPost) details() {  
    fmt.Println("Title: ", p.title)
    fmt.Println("Content: ", p.content)
    fmt.Println("Author: ", p.fullName())
    fmt.Println("Bio: ", p.bio)
}

现在我们已经准备好了 author 和 blogPost 结构体,让我们通过创建一个博客文章来完成这个程序。

创建博客文章

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 blogPost struct {  
    title   string
    content string
    author
}

func (b blogPost) details() {  
    fmt.Println("Title: ", b.title)
    fmt.Println("Content: ", b.content)
    fmt.Println("Author: ", b.fullName())
    fmt.Println("Bio: ", b.bio)
}

func main() {  
    author1 := author{
        "Naveen",
        "Ramanathan",
        "Golang Enthusiast",
    }
    blogPost1 := blogPost{
        "Inheritance in Go",
        "Go supports composition instead of inheritance",
        author1,
    }
    blogPost1.details()
}

运行示例

该程序运行结果如下

go blogpost 运行结果


嵌入结构体切片

我们可以更进一步地使用这个示例,并使用一个博客文章的切片e)创建一个网站:)。

让我们先定义 website 结构体。 在现有程序的主函数上方添加以下代码并运行它。

type website struct {  
        []blogPost
}
func (w website) contents() {  
    fmt.Println("Contents of Website\n")
    for _, v := range w.blogPosts {
        v.details()
        fmt.Println()
    }
}

添加上面代码后运行上面的程序时,编译器会如下错误

main.go:31:9: syntax error: unexpected [, expecting field name or embedded type  

此错误是由切片[]blogPost引起的。原因是不可能匿名嵌入切片。需要字段名。因此,让我们修复此错误并使编译器能编译通过。

type website struct {  
        blogPosts []blogPost
}

添加字段 blogPosts,它是一个切片 []blogPosts。

现在让我们修改 main 函数并为我们的新网站创建一些帖子。

修改main函数后的完整程序如下

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 blogPost struct {  
    title   string
    content string
    author
}

func (p blogPost) details() {  
    fmt.Println("Title: ", p.title)
    fmt.Println("Content: ", p.content)
    fmt.Println("Author: ", p.fullName())
    fmt.Println("Bio: ", p.bio)
}

type website struct {  
    blogPosts []blogPost
}

func (w website) contents() {  
    fmt.Println("Contents of Website\n")
    for _, v := range w.blogPosts {
        v.details()
        fmt.Println()
    }
}

func main() {  
    author1 := author{
        "Naveen",
        "Ramanathan",
        "Golang Enthusiast",
    }
    blogPost1 := blogPost{
        "Inheritance in Go",
        "Go supports composition instead of inheritance",
        author1,
    }
    blogPost2 := blogPost{
        "Struct instead of Classes in Go",
        "Go does not support classes but methods can be added to structs",
        author1,
    }
    blogPost3 := blogPost{
        "Concurrency",
        "Go is a concurrent language and not a parallel one",
        author1,
    }
    w := website{
        blogPosts: []blogPost{blogPost1, blogPost2, blogPost3},
    }
    w.contents()
}

运行示例

运行结果如下

go website 运行结果

在上面的 main 函数中,我们创建了一个作者 author1 和三个帖子 post1、post2 和 post3。 最后,我们中创建了网站 w

上一篇:Go 语言 mod 初始化失败问题解决

下一篇:没有了

除非注明转载,本站文章均为原创或翻译,欢迎转载,转载请以链接形式注明出处

本文地址:

迹忆客

专注技术分享,项目实战分享!

技术宅 乐于分享 7年编程经验
社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

热门文章

教程更新

热门标签

Go