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)
}

在上面的代码段中,我们创建了一个 author结构,它具有 firstNamelastNamebio字段。并且,我们还为 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)
}

post3 个字段,其中 titlecontent 是命名字段,而 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)
}

既然我们已经有了 authorpost结构,我们来写 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 行,我们创建了一个类型为 authorauthor1对象。
在第 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 篇博客 — post1post2post3。最后,通过嵌入 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  

这就是所有内容了~

祝你出门捡到钱~


原作者留言

优质内容来之不易,您可以通过该 链接 为我捐赠。


最后

感谢原作者的优质内容。

欢迎指出文中的任何错误。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值