Go 和 Java 不同,他没有类(class)的概念,但这并不是说Go不支持面向对象编程,毕竟面向对象是一种思想。
面向对象三大基本特征
- 封装:隐藏对象属性和实现细节,仅对外提供公共访问方式
- 继承:使子类继承父类的属性和方法,或者是子类重写父类的属性和方法
- 多态:不同对象中同种行为不同的实现方式
封装
Go 语言中可以使用结构体对属性进行封装。结构体好比类的一种简化形式,比如我们定义一个学生,学生有名字和性别,就像下面这样我们就定义了一个学生的结构体。不过结构体当中只定义了属性这点和 Java 就有这很大的差别,Java的属性和方法都是定义再类当中的,但是在 Go 当中 声明结构体,结构体中只声明了属性,方法却是在结构体之外。
属性
结构体里面定义了两个属性,并声明类型,现在属性有了是不是还缺少方法呢?别急,我们看下面
type Student struct {
Name string
age int
}
方法
这里定义了一个吃饭的方法,创建对象以后,通过对象调用方法,
package main
import "fmt"
func main() {
stu := Student{"zhang", 12}
fmt.Println(stu.Eat()) // zhang正在东西
}
type Student struct {
Name string
age int
}
func (stu *Student) Eat() string {
return stu.Name + "正在东西"
}
关于访问权限的问题
在 GO 中是没有 public、private 等等这些权限修饰符的。
那么GO是通过什么来实现权限控制的呢?
原来在GO当中,通过定义变量、常量、类型、结构体、函数等的名称就可以控制访问权限了,首字符大写就相当于public,允许其他包访问,如果是小写的话,相当于private,只能在当前包中使用。学到这里想必你已经清楚如何定义和私有化结构体属性了,然后就可以封装set、get方法了。
继承
Go 中没有 extents 关键字,而是在结构体中内嵌匿名字段来实现继承,下面直接写了一个示例来展示这个关系,这样写的话,需要在 Student 初始化赋值的时候,也要将 People 初始化赋值。
package main
import "fmt"
type People struct {
name string
}
// 人类描述吃的方法
func (p People) eat() {
fmt.Println(p.name + "正在吃东西")
}
// 模拟构造方法
func newPeople(name string) *People {
return &People{name: name}
}
// 匿名属性继承
type Student struct {
*People
}
// 模拟构造方法
func newStudent(name string) *Student {
return &Student{
People: newPeople(name),
}
}
func main() {
stu := newStudent("zhangsan")
stu.eat()
// 打印:zhangsan正在吃东西
}
多态
在面向对象中多态是由不同对象的同种行为的不同实现方式。
package main
import "fmt"
// 定义人的工作行为
type People interface {
task()
}
// 定义老师结构体
type Teacher struct {
taskName string
}
func (t Teacher) task() {
fmt.Println("老师的工作是:" + t.taskName)
}
// 定义学生结构体
type Student struct {
taskName string
}
func (s Student) task() {
fmt.Println("学生的工作是:" + s.taskName)
}
func main() {
t := &Teacher{"教书育人"}
s := &Student{"好好学习"}
// 这里向上赋值,在这个切片里,t 和 s 都是 People 类型了
p := []People{t, s}
for i, _ := range p {
p[i].task()
}
}
// 老师的工作是:教书育人
// 学生的工作是:好好学习
代码解析
我们定义了两个 task() 函数,分别为老师的任务和学生的任务,于是定义了一个包含 task() 的 People 接口,让 老师和学生 的两个函数都实现这个接口的函数。最后输出结果都执行了各自的任务,展现了多态的特征。
结尾
我是从 Java 转到 Go 的,我觉的 Go 的面向对象用起来没 Java 那么清晰明了,感觉有点混乱哈(不知道是不是不习惯的原因😁),然后就是,做项目的话,还是要看需求再决定是否使用**面向对象,**因为有的时候项目并不复杂完全没有必要使用继承多态等等,反而会增加项目的复杂度(有一个例子就是我前两天在写一个清单小程序的时候,封装了下get set 还有 继承接口这些,感觉完全没必要,直接写就好啦,看着还简洁呢)。
总体来说还是看需求哈,不能盲目的使用😊