[关闭]
@adamhand 2019-02-14T03:05:34.000000Z 字数 2423 阅读 963

golang--组合取代继承


Go 不支持继承,但它支持组合(Composition)。

通过嵌套结构体进行组合

在 Go 中,通过在结构体内嵌套结构体,可以实现组合。

组合的典型例子就是博客帖子。每一个博客的帖子(Post)都有标题、内容和作者信息(author)。“作者信息”这个结构体内嵌在“帖子”这个结构体中。

下面写一个这个例子。

  1. package main
  2. import "fmt"
  3. type author struct {
  4. firstName string
  5. lastName string
  6. bio string
  7. }
  8. func (a author)fullName() string {
  9. return fmt.Sprintf("%s %s", a.firstName, a.lastName)
  10. }
  11. type post struct {
  12. title string
  13. content string
  14. author
  15. }
  16. func (p post)details() {
  17. fmt.Println("title: ", p.title)
  18. fmt.Println("content: ", p.content)
  19. //一旦结构体内嵌套了一个结构体字段,Go 可以使我们访问其嵌套的字段,好像这些字段属于外部结构体一样。
  20. fmt.Println("author: ", p.author.fullName()) //可替换为p.fullName()
  21. fmt.Println("bio: ", p.author.bio) //可替换为p.bio
  22. }
  23. func main() {
  24. author1 := author{
  25. "Naveen",
  26. "Ramanathan",
  27. "Golang Enthusiast",
  28. }
  29. post1 := post{
  30. "Inheritance in Go",
  31. "Go supports composition instead of inheritance",
  32. author1,
  33. }
  34. post1.details()
  35. }

改程序的执行结果为:

  1. title: Inheritance in Go
  2. content: Go supports composition instead of inheritance
  3. author: Naveen Ramanathan
  4. bio: Golang Enthusiast

结构体切片的嵌套

可以进一步处理这个示例,使用博客帖子的切片来创建一个网站。

  1. package main
  2. import "fmt"
  3. type author struct {
  4. firstName string
  5. lastName string
  6. bio string
  7. }
  8. func (a author)fullName() string {
  9. return fmt.Sprintf("%s %s", a.firstName, a.lastName)
  10. }
  11. type post struct {
  12. title string
  13. content string
  14. author
  15. }
  16. func (p post)details() {
  17. fmt.Println("title: ", p.title)
  18. fmt.Println("content: ", p.content)
  19. //一旦结构体内嵌套了一个结构体字段,Go 可以使我们访问其嵌套的字段,好像这些字段属于外部结构体一样。
  20. fmt.Println("author: ", p.author.fullName()) //可替换为p.fullName()
  21. fmt.Println("bio: ", p.author.bio) //可替换为p.bio
  22. }
  23. type website struct {
  24. posts []post
  25. }
  26. func (w website)contents() {
  27. fmt.Println("website contents: ")
  28. fmt.Println()
  29. for _, v := range w.posts{
  30. v.details()
  31. fmt.Println()
  32. }
  33. }
  34. func main() {
  35. author1 := author{
  36. "Naveen",
  37. "Ramanathan",
  38. "Golang Enthusiast",
  39. }
  40. post1 := post{
  41. "Inheritance in Go",
  42. "Go supports composition instead of inheritance",
  43. author1,
  44. }
  45. post2 := post{
  46. "Struct instead of Classes in Go",
  47. "Go does not support classes but methods can be added to structs",
  48. author1,
  49. }
  50. post3 := post{
  51. "Concurrency",
  52. "Go is a concurrent language and not a parallel one",
  53. author1,
  54. }
  55. w := website{
  56. posts: []post{post1, post2, post3},
  57. }
  58. w.contents()
  59. }

上述程序的执行结果为:

  1. website contents:
  2. title: Inheritance in Go
  3. content: Go supports composition instead of inheritance
  4. author: Naveen Ramanathan
  5. bio: Golang Enthusiast
  6. title: Struct instead of Classes in Go
  7. content: Go does not support classes but methods can be added to structs
  8. author: Naveen Ramanathan
  9. bio: Golang Enthusiast
  10. title: Concurrency
  11. content: Go is a concurrent language and not a parallel one
  12. author: Naveen Ramanathan
  13. bio: Golang Enthusiast

需要注意的是,结构体不能嵌套一个匿名切片。如果上面website结构体像下面的写法:

  1. type website struct {
  2. []post
  3. }

就会报错,syntax error: unexpected [, expecting field name or embedded type

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注