迹忆客 专注技术分享

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

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

作者:迹忆客 最近更新:2023/01/08 浏览次数:

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

转载请发邮件至 1244347461@qq.com 进行申请,经作者同意之后,转载请以链接形式注明出处

本文地址:

相关文章

使用 C 语言中的 goto 语句

发布时间:2023/05/07 浏览次数:79 分类:C语言

本文介绍了如何在 C 语言中使用 goto 语句。使用 goto 语句在 C 语言中实现循环 goto 关键字是 C 语言的一部分,它提供了一个做无条件跳转的结构。

Django 中的 Slug

发布时间:2023/05/04 浏览次数:173 分类:Python

本篇文章旨在定义一个 slug 以及我们如何使用 slug 字段在 Python 中使用 Django 获得独特的帖子。

Django ALLOWED_HOSTS 介绍

发布时间:2023/05/04 浏览次数:181 分类:Python

本文展示了如何创建您的 Django 网站,为公开发布做好准备,如何设置 ALLOWED_HOSTS 以及如何在使用 Django 进行 Web 部署期间修复预期的主要问题。

Django 中的 Select_related 方法

发布时间:2023/05/04 浏览次数:129 分类:Python

本文介绍了什么是查询集,如何处理这些查询以及我们如何利用 select_related() 方法来过滤 Django 中相关模型的查询。

在 Django 中上传媒体文件

发布时间:2023/05/04 浏览次数:198 分类:Python

在本文中,我们简要介绍了媒体文件以及如何在 Django 项目中操作媒体文件。

Django 返回 JSON

发布时间:2023/05/04 浏览次数:106 分类:Python

在与我们的讨论中,我们简要介绍了 JSON 格式,并讨论了如何借助 Django 中的 JsonResponse 类将数据返回为 JSON 格式。

在 Django 中创建对象

发布时间:2023/05/04 浏览次数:59 分类:Python

本文的目的是解释什么是模型以及如何使用 create() 方法创建对象,并了解如何在 Django 中使用 save() 方法。

扫一扫阅读全部技术教程

社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便