在java中方法和函数的含义是一样的,只是不同的叫法,但是在golang中却是有区别的。我们先来看一下函数和方法在golang中的定义有什么差别。
// user 在程序里定义一个用户类型
type user struct {
name string
email string
}
// 定义一个 notify 方法
func (u user) notify() {
fmt.Printf("Sending User Email To %s<%s>\n",
u.name,
u.email)
}
// 定义一个 notify 函数
func notify(u user) {
fmt.Printf("Sending User Email To %s<%s>\n",
u.name,
u.email)
}
看出有什么不同了嘛,方法的名称前面多了一个括号传递参数,里面传了一个user类型的对象,官方的解释是
简单地说就跟java的成员方法一样,需要先实例化一个对象,才能通过对象去调用类里面定义的方法,user就是所谓的接收者。而函数就有点类似java里的静态方法了,可以直接调用,不需要通过实例化对象再通过对象去调用,可以直接调用。
func main() {
// 创建一个user对象
bill := user{"Bill", "bill@email.com"}
//方法调用
bill.notify()
//函数调用
notify(bill)
}
下面我们看一下golang接口是怎么定义的,接口的含义和java中的差不多,都是定义一组需要实现的方法集
type notifier interface {
notify()
}
实现的方式想必大家也能猜出来了,上面的定义的方法其实就是接口的实现方式,与java中不一样的是,golang中没有实现接口的关键字,实现接口不需要显式地去声明实现接口,只要实现了接口中定义的所有方法,就算是实现了这个接口了
type notifier interface {
notify()
}
type user struct {
name string
email string
}
func (u user) notify() {
fmt.Printf("Sending user email to %s<%s>\n",
u.name,
u.email)
}
func sendNotification(n notifier) {
n.notify()
}
func main() {
u := user{"Bill", "bill@email.com"}
sendNotification(u)
}
golang中的面向对象特性并不像java中实现的那么完善,下面再说一下多态和继承在golang中是怎么实现的。
下面是一段多态的实现代码,admin和user都实现了notify的方法,都是notifier接口的实现,sendNotification根据实际传递的对象,分别调用了各自的notify的实现
type notifier interface {
notify()
}
type user struct {
name string
email string
}
func (u user) notify() {
fmt.Printf("Sending user email to %s<%s>\n",
u.name,
u.email)
}
type admin struct {
name string
email string
}
func (a admin) notify() {
fmt.Printf("Sending admin email to %s<%s>\n",
a.name,
a.email)
}
func main() {
bill := user{"Bill", "bill@email.com"}
sendNotification(bill)
lisa := admin{"Lisa", "lisa@email.com"}
sendNotification(lisa)
}
func sendNotification(n notifier) {
n.notify()
}
golang中的继承就比较特殊了,涉及到类型内嵌的概念,下面是官方的定义
一个字段可以仅由一个字段类型组成。 这样的字段声明方式称为类型内嵌(type embedding)
通俗的说就是,结构体定义了一个字段,只有类型没有给字段名称,就想下面的admin里面有个user类型的属性,却没有起个名称,有点像匿名属性。当一个结构体中内嵌了其他类型的结构体,就相当于继承了内嵌结构体的属性和方法,所以admin可以直接调用notify方法,尽管admin自己没有实现这个方法,可是内嵌的user实现了这个方法,admin就自然获得了user的属性和方法。
type user struct {
name string
email string
}
func (u user) notify() {
fmt.Printf("Sending user email to %s<%s>\n",
u.name,
u.email)
}
type admin struct {
user // 嵌入类型
level string
}
func (u admin) notify() {
fmt.Printf("Sending user email to %s<%s>\n",
u.name,
u.email)
}
func main() {
ad := admin{
user: user{
name: "john smith",
email: "john@yahoo.com",
},
level: "super",
}
ad.notify()
}