> For the complete documentation index, see [llms.txt](https://wskdsgcf.gitbook.io/mastering-go-zh-cn/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://wskdsgcf.gitbook.io/mastering-go-zh-cn/7-fan-she-he-jie-kou/07.6.md).

# 07.6 Go的OOP思想

现在应该了解Go语言缺少继承，但它支持组合，并且Go接口提供了一种多态性。所以，尽管Go不是面向对象的编程语言，但它有一些特性可以让您模拟面向对象的编程。

> 如果您真的想使用面向对象的方法开发应用程序，那么Go语言可能不是您的最佳选择。由于我不是很喜欢Java，我建议看一下C++或Python。当然，Go禁止构建复杂而深入的类型层次结构，也是因为这些深层次结构很难使用和维护！

首先，让我解释这一部分中将使用的两种Go语言技术。第一种技术使用方法将函数与类型关联起来。这意味着，在某种程度上，您可以考虑函数和数据类型构造了一个对象。

使用第二种技术，可以将数据类型嵌入到新的结构类型中，以便创建一种层次结构。

还有第三种技术，即使用Go接口生成两个或多个元素——一个类的多个对象。因为本章前面的章节刚刚进行了论述，本节将不介绍这种技术。这个技术的关键点是Go接口允许您在不同的元素之间定义一个共同的行为（函数方法），这样所有这些不同的元素都可以共享一个对象的特性，因此可以认为这些不同的元素是同一个类的对象。然而，实际的面向对象编程语言的对象和类可以做更多的事情。

前两种技术将在`ooo.go`程序中进行说明，该程序将分四部分介绍。`ooo.go`的第一段包含以下Go代码：

> ```go
> package main
>
> import (
>     "fmt"
> )
>
> type a struct {
>     XX int
>     YY int
> }
>
> type b struct {
>     AA string
>     XX int
> }
> ```

````
>```go
> type c struct {
>     A a
>     B b
> }
>
````

在Go语言中，组合技术允许使用多个`struct`类型创建一个新的结构。在以上代码示例中，数据类型`c`由一个结构体`a`的变量和一个结构体`b`的变量组合而成。

以下Go代码是`ooo.go`的第三部分：

> ```go
> func (A a) A() {
>     fmt.Println("Function A() for A")
> }
>
> func (B b) A() {
>     fmt.Println("Function A() for B")
> }
> ```

此处定义的两个方法可以使用相同的名称（`A()`），因为它们具有不同的函数头。第一种方法使用`a`变量，而第二种方法使用`b`变量。此技术允许您在多个类型之间共享相同的函数名。

代码`ooo.go`的最后一部分如下：

> ```go
> func main() {
>     var i c
>     i.A.A()
>     i.B.A()
> }
> ```

与实现**抽象类**和**继承**的面向对象编程语言代码相比，`ooo.go`中的所有Go代码都非常简单。而且，它对于生成具有结构的类型和元素，以及具有相同方法名的不同数据类型来说是足够的。

执行`ooo.go`程序的输出如下：

> ```
> $ go run ooo.go
> Function A() for A
> Function A() for B
> ```

以下代码则说明了组合与继承的差异，结构体`first`对结构体`second`调用`shared()`函数，对其所做的更改一无所知：

> ```go
> package main
>
> import (
>     "fmt"
> )
>
> type first struct{}
>
> func (a first) F() {
>     a.shared()
> }
>
> func (a first) shared() {
>     fmt.Println("This is shared() from first!")
> }
>
> type second struct {
>     first
> }
>
> func (a second) shared() {
>     fmt.Println("This is shared() from second!")
> }
>
> func main() {
>     first{}.F()
>     second{}.shared()
>     i := second{}
>     j := i.first
>     j.F()
> }
> ```

通过以上代码可以看到结构体`second`嵌入了结构体`first`，这两个结构体共享一个名为`shared()`的函数。

以上Go代码保存为goCoIn.go并执行，将生成以下输出：

> ```
> $ go run goCoIn.go
> This is shared() from first!
> This is shared() from second!
> This is shared() from first!
> ```

`first{}.F()`和`second{}.shared()`的函数调用生成了预期的结果。尽管结构体`second`重新实现了`shared()`函数，对`j.F()`的调用仍然调用了`first.shared()`而不是`second.shared()`函数。在面向对象语言的术语中这样的操作叫做`方法重写`。

另外可以将`j.F()`调用可以简写成`(i.first).F()`或`(second{}.first).F()`，而不需要定义太多的变量。为了更容易理解，上面的调用将这个过程分成三行代码。
