原文来自:https://golangbot.com/inheritance/
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)
}
上述代码片段,我们创建了一个结构体autuor,拥有成员firstName, lastName和bio。增加一个方法fullName(),author作为接收者类型。该方法返回结构体的全名。
下一步,我们创建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结构体的字段有title, content,同时嵌套一个匿名结构体author。该字段表明post结构体是由author结构体组合而成。现在结构体post可以访问author结构体的所有成员和方法。我们还给结构体post增加一个details()方法,用来打印title,content,fullName和author.bio.
一旦一个结构体嵌套另外一个结构体,Go访问嵌套结构体成员时,就好像是在访问自己结构体成员。也就是说p.author.fullName()可以用p.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结构体,现在我们可以实现一个博客帖子:
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()
}
程序打印结果:
Title: Inheritance in Go
Content: Go supports composition instead of inheritance
Author: Naveen Ramanathan
Bio: Golang Enthusiast
结构体嵌套切片
我们可以进一步处理这个实例,用博客帖子的切片来创建一个网站。
首先定义website结构体。在main函数上方增加以下代码:
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.这是因为切片嵌套结构体时不能匿名(结构体可以匿名,如post中的author)。修改错误:
type website struct {
posts []post
}
给结构体website的切片成员增加成员变量名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()
}
程序执行结果:
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
本节课程到此结束。Have a great day.
ps:新手翻译,欢迎大家指正!