Go的OOP思想

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

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

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

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

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

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

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. type a struct {
  6. XX int
  7. YY int
  8. }
  9. type b struct {
  10. AA string
  11. XX int
  12. }
  1. >```go
  2. > type c struct {
  3. > A a
  4. > B b
  5. > }
  6. >

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

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

  1. func (A a) A() {
  2. fmt.Println("Function A() for A")
  3. }
  4. func (B b) A() {
  5. fmt.Println("Function A() for B")
  6. }

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

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

  1. func main() {
  2. var i c
  3. i.A.A()
  4. i.B.A()
  5. }

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

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

  1. $ go run ooo.go
  2. Function A() for A
  3. Function A() for B

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

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. type first struct{}
  6. func (a first) F() {
  7. a.shared()
  8. }
  9. func (a first) shared() {
  10. fmt.Println("This is shared() from first!")
  11. }
  12. type second struct {
  13. first
  14. }
  15. func (a second) shared() {
  16. fmt.Println("This is shared() from second!")
  17. }
  18. func main() {
  19. first{}.F()
  20. second{}.shared()
  21. i := second{}
  22. j := i.first
  23. j.F()
  24. }

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

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

  1. $ go run goCoIn.go
  2. This is shared() from first!
  3. This is shared() from second!
  4. 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(),而不需要定义太多的变量。为了更容易理解,上面的调用将这个过程分成三行代码。