美文网首页
Go教程第二十三篇: Go中的面向对象:组合而不是继承

Go教程第二十三篇: Go中的面向对象:组合而不是继承

作者: 大风过岗 | 来源:发表于2020-05-18 13:31 被阅读0次

本文是《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)
}

在上面的程序中,我们创建了一个author结构体,该结构体有字段: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结构体中添加了一个detail()方法。此方法会打印tile,content,fullName以及author的bio。

当一个结构体字段嵌入在另一个结构体中时,Go允许我们直接访问这个内嵌的字段就好像它是外层结构体的一部分一样。这也就意味着,p.author.fullName可以使用p.fullName代替。因此detail()方法可以重写如下:

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。原因是,无法嵌入一个匿名分片。我们需要为分片字段指定一个名字。我们来修复一下这个程序。

type website struct {
        posts []post
}

现在,我们为post分片[]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()
}

在上面的程序中,我们创建了一个作者author1,以及3个博客:post1、post2、post3。最后,通过内嵌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

感谢您的阅读,请留下您珍贵的反馈和评论。Have a good Day!

备注
本文系翻译之作原文博客地址

相关文章

  • Go教程第二十三篇: Go中的面向对象:组合而不是继承

    本文是《Go系列教程》的第二十三篇文章。 Go本身不支持继承,但是它支持组合。组合的通常定义是:“放置在一起”。组...

  • Go教程第二十四篇:结构体而非类

    Go中的面向对象:结构体而非类 本文是《Go系列教程》的第二十四篇文章。 Go是面向对象的吗? Go并不是一个纯面...

  • go语言学习(8)--Struct

    面向对象 go只支持封装,不支持继承和多态go是面向接口的编程,也可以说go所有对象都是继承了一个空接口java这...

  • Golang-TCP异步框架Tao分析

    TCP异步框架 Golang 编程风格 Go语言面向对象编程的风格是多用组合,少用继承,以匿名嵌入的方式实现继承。...

  • 【Golang 基础】Go 语言 面向对象

    Go 语言的面向对象   Go 语言的面向对象非常简单,仅支持封装,不支持继承和多态。继承和多态是在接口中实现的。...

  • 第13章-OOP面向对象编程

    面向对象(OOP) go并不是一个纯面向对象的编程语言。在go中的面向对象,结构体替换了类。 Go并没有提供类cl...

  • Golang(十三) OOP面向对象编程

    面向对象(OOP) go并不是一个纯面向对象的编程语言。在go中的面向对象,结构体替换了类。 Go并没有提供类cl...

  • struct

    面向对象编程 Go支持面向对象编程特性,但和传统面向对象编程是有区别的,Go并不是纯粹的面向对象语言。 Go没有类...

  • Go基础编程---面向对象

    面向对象 Go中没有发封装、继承、多态,但是可以通过方法、匿名字段、接口实现,Go中偏向于面向接口编程 匿名字段(...

  • Go基础语法(十二)

    面向对象编程 Go 并不是完全面向对象的编程语言。 Go 官网的 FAQ 回答了 Go 是否是面向对象语言,摘录如...

网友评论

      本文标题:Go教程第二十三篇: Go中的面向对象:组合而不是继承

      本文链接:https://www.haomeiwen.com/subject/tqeuohtx.html