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)
}
funcmain() {
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()
}
}
funcmain() {
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
。
本文转载自:迹忆客(https://www.jiyik.com)
以上是 Go 面向对象 - 组合 替代 继承 的全部内容, 来源链接: utcz.com/z/290230.html