您的位置 首页 golang

Go 面向对象 – 组合 替代 继承

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

在上面的代码片段中,我们创建了一个包含 firstName lastName bio 字段的 author 结构体。 我们还添加了一个fullName() 方法,该方法接收一个 author类型的参数,它返回作者的全名。

下一步是创建 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 组成。 现在 blogPost 结构可以访问 author 结构的所有字段和方法。 我们还向 blogPost 结构添加了 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)
}  

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

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

该程序运行结果如下


嵌入结构体切片

我们可以更进一步地使用这个示例,并使用一个博客文章的切片e)创建一个网站:)。

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

 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    

此错误是由切片 []blogPost 引起的。原因是不可能匿名嵌入切片。需要字段名。因此,让我们修复此错误并使编译器能编译通过。

 type website struct {  
        blogPosts []blogPost
}  

添加字段 blogPosts,它是一个切片 []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()
}  

运行结果如下

在上面的 main 函数中,我们创建了一个作者 author1 和三个帖子 post1、post2 和 post3。 最后,我们中创建了网站 w

文章来源:智云一二三科技

文章标题:Go 面向对象 – 组合 替代 继承

文章地址:https://www.zhihuclub.com/100977.shtml

关于作者: 智云科技

热门文章

网站地图