关于Go是否是面向对象编程语言,这个问题在GO的社区也有很多讨论,众说纷纭,而GO的官方给出的答案是:YES OR NO,是也不是。针对这个答案,我们可以从面向对象的一些特性来进行剖析一下。
是否面型对象
Go不是面向对象
1、Go本身是一门面向过程、并发编程的语言
2、Go 在语法上并不是典型的面向对象语言,它没有类(class)的概念,也没有继承(inheritance)和多态(polymorphism)的特性
Go是面向对象
1、虽然Go语言在语法上不是面向对象,但是提供一些面向对象编程的特性,这一点从java转到go的同学是深有体会,在刚进入go的编程时总会延用以前java的设计思路,感觉这就是一门面向对象的编程语言
Go面向对象特性
从上面的结论上我们也知道了,Go语言从设计和语法上本身不是一门面向对象的语言,但是它提供了一些面向对象的特性,使得开发人员可以写出类似面向对象设计的代码。面向对象的三大特性:封装、集成和多态,那么我们就从这三个特性看看Go是如何实现的
封装
封装是将数据(属性)和操作数据的方法(行为)捆绑在一起,形成一个独立的单元。通过封装,对象的内部实现细节被隐藏,只有对象的接口是可见的,外部代码无法直接访问对象的内部数据,在面向对象语言中,封装是类class提供的特性。
Go语言没有class的概念,但是提供了结构体(struct)的定义,我们可以在结构体里定义属性,然后通过创建结构体示例来访问属性,但是结构体内部无法封装行为,对结构体的行为是在结构体外部定义的。
package extension
import (
"fmt"
"testing"
)
//定义结构体
type Person struct {
Name string
Age int32
Address string
}
//定义行为
func (p *Person) speak() {
println(p.Name)
}
func TestPerson(t *testing.T) {
//创建实例
var person = new(Person)
//设置属性
person.Name = "张三"
person.Age = 20
person.Address = "武汉"
//调用行为
person.speak()
}
继承
继承允许一个类(子类/派生类)继承另一个类(父类/基类)的属性和方法。子类可以继承父类的特性,可以重用父类的代码,并且可以在不修改父类代码的情况下进行扩展。
Go的语法里并没有继承的概念,但是可以通过组合的使用来达到类似继承的效果,但是这种做法本身和继承又有一些区别。
继承父类方法:
package extension
import (
"fmt"
"testing"
)
type Pet struct {
}
func (p *Pet) Speak() {
fmt.Print("pig")
}
type Dog struct {
Pet //继承Pet
}
func TestDog(t *testing.T) {
dog := new(Dog)
dog.Speak() //调用Pet方法
}
//输出pig
重写父类方法:
package extension
import (
"fmt"
"testing"
)
type Pet struct {
}
func (p *Pet) Speak() {
fmt.Print("pig!")
}
func (p *Pet) SpeakTo(host string) {
p.Speak()
fmt.Println(" ", host)
}
type Dog struct {
Pet //继承Pet
}
func (d *Dog) Speak() {
fmt.Print("dog!")
}
func TestDog(t *testing.T) {
dog := new(Dog)
dog.Speak() //调用Pet方法
}
//输出dog
父类调用子类方法:这里可以看出差别,并不是真的继承
package extension
import (
"fmt"
"testing"
)
type Pet struct {
}
func (p *Pet) Speak() {
fmt.Print("pig!")
}
func (p *Pet) SpeakTo(host string) {
p.Speak()
fmt.Println(" ", host)
}
type Dog struct {
Pet //继承Pet
}
func (d *Dog) Speak() {
fmt.Print("dog!")
}
func TestDog(t *testing.T) {
dog := new(Dog)
dog.SpeakTo("host") //调用父类方法
}
//输出pig而不是dog
多态
多态允许不同类的对象对同一个消息(方法调用)作出响应,这个消息可以是类的方法。在多态中,同样的方法可以有不同的实现,具体执行哪个实现是在运行时决定的。多态提高了代码的灵活性和可扩展性。
在面向对象语言中,多态和继承一般是紧密相连的,但是在Go中没有继承的概念,多态的特性是通过接口(interface)来实现。
package interface_test
import "testing"
type Pet struct {
}
func (p *Pet) eat() {
fmt.Print("pig!")
}
type Dog struct {
}
func (d *Dog) eat() {
fmt.Print("dog!")
}
type Animal interface {
eat()
}
func TestAnimal(t *testing.T) {
var a Animal //定义一个Animal类型变量
a = new(Pet)
a.eat()
//输出pig!
a = new(Dog)
a.eat()
//输出dog!
}
上面这个代码是不是完全就是多态的行为了。
到这里大家对Go是否是一门面向对象的语言是不是已经有了答案,就单从语言的语法和设计上来看Go确实不是一门面向对象语言,但是它里面提供了一些面向对象的特性,我们可以采用不同的方式来实现面向对象的一些设计,所以这里说的是提供了面向对象的特性。