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)
}
在上面的代码片段中,我们创建了一个包含 firstName
、lastName
和 bio
字段的 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 结构体具有 title
、content
字段。 它还具有嵌入式匿名字段 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() }
该程序运行结果如下
嵌入结构体切片
我们可以更进一步地使用这个示例,并使用一个博客文章的切片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() }
运行结果如下
在上面的 main 函数中,我们创建了一个作者 author1 和三个帖子 post1、post2 和 post3。 最后,我们中创建了网站 w
。
相关文章
使用 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 中按降序过滤查询集中的项目
发布时间:2023/05/04 浏览次数:157 分类:Python
-
在这个讲解中,学习如何借助 Django 中的 order_by() 方法按降序过滤出查询集中的项目。
Django ALLOWED_HOSTS 介绍
发布时间:2023/05/04 浏览次数:181 分类:Python
-
本文展示了如何创建您的 Django 网站,为公开发布做好准备,如何设置 ALLOWED_HOSTS 以及如何在使用 Django 进行 Web 部署期间修复预期的主要问题。
Django 中的 Select_related 方法
发布时间:2023/05/04 浏览次数:129 分类:Python
-
本文介绍了什么是查询集,如何处理这些查询以及我们如何利用 select_related() 方法来过滤 Django 中相关模型的查询。
使用 Post 请求将数据发送到 Django 服务器
发布时间:2023/05/04 浏览次数:159 分类:Python
-
在这篇关于Django的讲解中,我们简要介绍了post和get请求以及如何在Django中用post实现CSRF token。
Django 返回 JSON
发布时间:2023/05/04 浏览次数:106 分类:Python
-
在与我们的讨论中,我们简要介绍了 JSON 格式,并讨论了如何借助 Django 中的 JsonResponse 类将数据返回为 JSON 格式。
在 Django 中创建对象
发布时间:2023/05/04 浏览次数:59 分类:Python
-
本文的目的是解释什么是模型以及如何使用 create() 方法创建对象,并了解如何在 Django 中使用 save() 方法。