组合是一种用于编写可重用代码段的方法。当对象由具有特定行为的其他较小对象组成时就可以实现,换句话说,具有更广泛功能的较大对象嵌入具有特定行为的较小对象。组合的最终目标与继承相同,但是,在这方面,更大的对象不是从父类/对象继承特性,而是由其他对象组成,从而可以使用它们的功能。
由于在 Go 语言中编写有效的代码主要围绕使用结构和接口,因此组合是该语言必须提供的内容的关键。在本文中,我们将通过类型嵌入讨论使用类型与结构和接口的组合:
示例 1:结构的组合
// Golang program to store information
// about games in structs and display them
package main
import "fmt"
// We create a struct details to hold
// generic information about games
type details struct {
genre string
genreRating string
reviews string
}
// We create a struct game to hold
// more specific information about
// a particular game
type game struct {
name string
price string
// We use composition through
// embedding to add the
// fields of the details
// struct to the game struct
details
}
// this is a method defined
// on the details struct
func (d details) showDetails() {
fmt.Println("Genre:", d.genre)
fmt.Println("Genre Rating:", d.genreRating)
fmt.Println("Reviews:", d.reviews)
}
// this is a method defined
// on the game struct
// this method has access
// to showDetails() as well since
// the game struct is composed
// of the details struct
func (g game) show() {
fmt.Println("Name: ", g.name)
fmt.Println("Price:", g.price)
g.showDetails()
}
func main() {
// defining a struct
// object of Type details
action := details{"Action","18+", "mostly positive"}
// defining a struct
// object of Type game
newGame := game{"XYZ","$125", action}
newGame.show()
}
输出:
Name: XYZ
Price: $125
Genre: Action
Genre Rating: 18+
Reviews: mostly positive
说明:在上面的代码片段中,我们创建了两个结构体: details和game 。结构详细信息包括有关游戏的通用信息。结构体游戏是一个复合结构体,它有自己的领域和细节领域。这种组合是通过类型嵌入实现的,因此第一个结构体变成了一段可重用的代码。
有趣的是,在 struct details上定义的方法可以被 type game 的对象访问,因为game是由details组成的。
示例 2:通过嵌入接口进行组合
在 Go 语言中,接口是隐式实现的。也就是说,如果在接口中定义的方法用于诸如结构之类的对象,则称该结构实现了该接口。一个接口可以嵌入其他接口以形成复合接口。如果复合接口中的所有接口都实现了,那么复合接口也被认为是由该对象实现的。
// Golang Program to implement composite interfaces
package main
import "fmt"
type purchase interface {
sell()
}
type display interface {
show()
}
// We use the two previous
// interfaces to form
// The following composite
// interface through embedding
type salesman interface {
purchase
display
}
type game struct {
name, price string
gameCollection []string
}
// We use the game struct to
// implement the interfaces
func (t game) sell() {
fmt.Println("--------------------------------------")
fmt.Println("Name:", t.name)
fmt.Println("Price:", t.price)
fmt.Println("--------------------------------------")
}
func (t game) show() {
fmt.Println("The Games available are: ")
for _, name := range t.gameCollection {
fmt.Println(name)
}
fmt.Println("--------------------------------------")
}
// This method takes the composite
// interface as a parameter
// Since the interface is composed
// of purchase and display
// Hence the child methods of those
// interfaces can be accessed here
func shop(s salesman) {
fmt.Println(s)
s.sell()
s.show()
}
func main() {
collection := []string{"XYZ",
"Trial by Code", "Sea of Rubies"}
game1 := game{"ABC", "$125", collection}
shop(game1)
}
输出:
{ABC $125 [XYZ Trial by Code Sea of Rubies]}
--------------------------------------
Name: ABC
Price: $125
--------------------------------------
The Games available are:
XYZ
Trial by Code
Sea of Rubies
--------------------------------------
说明:首先,我们创建了 2 个接口购买和展示,它们有自己的方法原型。然后我们将它们嵌入到接口销售员中,以形成一个复合结构。这演示了 Go Lang 中组合概念的使用。在 shop() 方法中,我们通过在方法中传递 Type game 对象来实现销售员接口。由于这个方法实现了复合接口,我们可以访问我们最初声明的两个接口的子方法。这样,可以通过干净的可重用代码进行有效的 go 编程。