Go 中的 OOP -组合而不是继承

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的结构体。同时我们还增加fullName的方法,该方法返回作者的全名。

下一步是创建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 组成。

现在blogPoststruct 可以访问author结构的所有字段和方法。我们还在结构中添加了打印作者的标题、内容、全名和简介的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)
}

现在我们已经准备好了authorblogPost结构,让我们通过创建一篇博客文章来完成这个程序。

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

func main() {  
    author1 := author{
        "Naveen",
        "Ramanathan",
        "Golang Enthusiast",
    }
    blogPost1 := blogPost{
        "Inheritance in Go",
        "Go supports composition instead of inheritance",
        author1,
    }
    blogPost1.details()
}

Run in playground

上面程序的主要功能是创建一个新作者和创建了一个新帖子。调用嵌入author.的details()方法

该程序打印,

Title:  Inheritance in Go  
Content:  Go supports composition instead of inheritance  
Author:  Naveen Ramanathan  
Bio:  Golang Enthusiast  

嵌入结构体切片

我们可以更进一步地使用这个示例,并使用一部分博客文章创建一个网站。

我们首先定义website结构体。请在现有程序的main函数上方添加以下代码并运行。

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  

此错误指向 struct 的嵌入切片[]blogPost。原因是无法匿名嵌入切片。需要字段名称。因此,让我们修复这个错误,让编译器满意。

type website struct {  
        blogPosts []blogPost
}

我添加了blogPosts一个 slice字段[]blogPosts

现在让我们修改主要功能并为我们的新网站创建一些帖子。

下面给出修改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()
    }
}

func main() {  
    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()
}

Run in playground

在上面的 main 函数中,我们创建了一个作者author1和三个帖子post1,post2post3。最后创建了网站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、付费专栏及课程。

余额充值