导言
- 原文链接: Part 27: Composition Instead of Inheritance - OOP in Go
- If translation is not allowed, please leave me in the comment area and I will delete it as soon as possible.
组合而不是继承
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)
}
在上面的代码段中,我们创建了一个 author
结构,它具有 firstName
、lastName
、bio
字段。并且,我们还为 author
结构 添加了 fullName
方法。
下一步,我们创建 post
结构。
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
有 3
个字段,其中 title
、content
是命名字段,而 author
是匿名字段,这个字段表示 post
结构 由 author
结构 组和而成。此时,post
结构 能访问 author
结构 的所有字段和方法。接下来,我们还为 post
结构 添加了 details
方法。
当一个结构嵌入另一个结构时,外部结构能直接访问内部结构的字段,仿佛这些字段属于外部结构。
这句话的意思就是:我们可以使用 p.fullName()
去代替 p.author.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)
}
既然我们已经有了 author
、post
结构,我们来写 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 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()
}
在第 31
行,我们创建了一个类型为 author
的 author1
对象。
在第 36
行,通过将 author1
嵌入 post
结构,我们创建了 post1
对象。
程序输出如下:
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
切片定义一个名字。
修改后的 websize
结构 如下:
type website struct {
posts []post
}
接下来,我们修改下 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 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()
}
在上面的 main
函数 中,我们创建了一个作家 — author1
,还有 3
篇博客 — post1
、 post2
和 post3
。最后,通过嵌入 3
篇博客,我们创建了一个网页 — w
。
运行程序,输出如下:
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
这就是所有内容了~
祝你出门捡到钱~
原作者留言
优质内容来之不易,您可以通过该 链接 为我捐赠。
最后
感谢原作者的优质内容。
欢迎指出文中的任何错误。