Go 并不是完全面向对象的编程语言
可以说是,也可以说不是。虽然 Go 有类型和方法,支持面向对象的编程风格,但却没有类型的层次结构。
Go 中的“接口”概念提供了一种不同的方法,我们认为它易于使用,也更为普遍。
Go 也可以将结构体嵌套使用,这与子类化(Subclassing)类似,但并不完全相同。
此外,Go 提供的特性比 C++ 或 Java 更为通用:子类可以由任何类型的数据来定义,甚至是内建类型(如简单的“未装箱的”整型)。
这在结构体(类)中没有受到限制。
使用结构体,而非类
Go 不支持类,而是提供了结构体。结构体中可以添加方法。这样可以将数据和操作数据的方法绑定在一起,实现与类相似的效果。
还记得函数和方法的区别吗???,自己回一下
简单的一个结构体和方法,代码如下:
package main
import "oop/employee"
func main() {
e := employee.Employee {
FirstName: "Sam",
LastName: "Adolf",
TotalLeaves: 30,
LeavesTaken: 20,
}
//var e employee.Employee // 如果这么定义,输出 has 0 leaves remaining,没有意义
e.LeavesRemaining()
}
结果:
Sam Adolf has 10 leaves remaining
使用 New() 函数,而非构造器
当创建结构体时,必须带有初始值,就要用到New()函数
Go 并不支持构造器。如果某类型的零值不可用,需要程序员来隐藏该类型,避免从其他包直接访问。
程序员应该提供一种名为 NewT(parameters) 的 函数,按照要求来初始化 T 类型的变量。
按照 Go 的惯例,应该把创建 T 类型变量的函数命名为 NewT(parameters)。这就类似于构造器了。
如果一个包只含有一种类型,按照 Go 的惯例,应该把函数命名为 New(parameters), 而不是 NewT(parameters)。
func New(参数列表) T{}
修改步骤:
1,结构体不可引用(首字母小写
)
2,用New()函数创建结构体变量
package employee
import "fmt"
func init() {
fmt.Println("init--------------------")
}
//变量名称,函数名称,结构体名称大小写的区别
//在 Go 中,当变量或函数的首字母大写的时候,函数会被从包中导出(在包外部可见,或者说公有的)
//公有函数的名字以大写字母开头
//私有函数的名字以小写字母开头
type employee struct {
FirstName string
LastName string
TotalLeaves int
LeavesTaken int
}
func New(firstName string, lastName string, totalLeave int, leavesTaken int) employee {
e := employee{firstName, lastName, totalLeave, leavesTaken}
return e;
}
func (e employee) LeavesRemaining() {
//fmt.Println(e)
fmt.Printf("%s %s has %d leaves remaining", e.FirstName, e.LastName, (e.TotalLeaves - e.LeavesTaken))
}
测试代码:
package main
import "model/employee"
func main() {
/*e := employee.Employee{
FirstName: "Sam",
LastName: "Adolf",
TotalLeaves: 30,
LeavesTaken: 20,
}*/
//var te = employee.Employee // 报错: undefined: employee.Employee
e := employee.New("Sam","Adolf",30,20)
e.LeavesRemaining()
}
虽然 Go 不支持类,但结构体能够很好地取代类,而以 New(parameters)
签名的方法可以替代构造器。