面向对象 – 结构体

  首先说一个概念性问题

  • Go 语言仅支持封装,不支持继承和多态;
  • GO 语言没有 class ,只有 struct;

  Go 语言的结构体(struct)和其他语言的类(class)有同等的地位,但 Go 语言放弃了包括继承在内的大量面向对象特性,只保留了组合(composition)这个最基础的特性。

  组合甚至不能算面向对象特性,因为在 C 语言这样的过程式编程语言中,也有结构体,也有组合。组合只是形成复合类型的基础。

  原来说过,所有的 Go 语言类型(指针类型除外)都可以有自己的方法。在这个背景下,Go语言的结构体只是很普通的复合类型,平淡无奇。例如,我们要定义一个矩形类型:

type Rect struct {
    x, y float64
    width, height float64
}

  然后我们定义成员方法 Area()来 计算矩形的面积:

func (r *Rect) Area() float64 {
    return r.width * r.height
}

  可以看出, Go 语言中结构体的使用方式与 C 语言并没有明显不同。

初始化

  在定义了 Rect 类型后,该如何创建并初始化 Rect 类型的对象实例呢?这可以通过如下几种方法实现:

rect1 := new(Rect)
rect2 := &Rect{}
rect3 := &Rect{0, 0, 100, 200}
rect4 := &Rect{width: 100, height: 200}

  在 Go 语言中,未进行显式初始化的变量都会被初始化为该类型的零值,例如 bool 类型的零值为 false,int 类型的零值为0,string 类型的零值为空字符串。

  在 Go 语言中没有构造函数的概念,对象的创建通常交由一个全局的创建函数来完成,以 NewXXX 来命名,表示“构造函数”:

func NewRect(x, y, width, height float64) *Rect {
    return &Rect{x, y, width, height}
}

  这一切非常自然,开发者也不需要分析在使用了 new 之后到底背后发生了多少事情。在 Go 语言中,一切要发生的事情都直接可以看到。

结构创建在堆上还是桟上?

  答:不需要知道。这个是有 Go 的编译器和运行环境决定的,如下面的代码

func NewRect(x, y, width, height float64) *Rect {
    return &Rect{x, y, width, height}
}

  上方代码,返回的是一个取地址返回的变量,那这里就是在堆上开内存空间,在外部有人在使用这个变量,那么这个变量就要参与垃圾回收,并不是说这个方法运行完毕变量就回收了,而是在外部没有引用之后再进行回收。反之亦然。

发表评论

电子邮件地址不会被公开。 必填项已用*标注