转载请附上本文地址: https://blog.csdn.net/u011957758/article/details/81125101
在Go里头是没有类的概念的,但是Go一样实现了同样的效果。
本文主要通过Go和PHP的对比来做笔记,致力于”一篇讲清楚go方法”,对于说phper的同学,看完印象会更深刻。
即将get到以下知识小点:
1.Go的方法 vs PHP的类
2.Go的继承 vs PHP的继承
3.重载?重写?
4.指针接收者的方法
5.封装&访问权限说明
几乎所有广泛应用的语言都支持面向对象编程的思想。当然go也不例外。
在php中的class类的概念,对应到go里头就是方法的概念。
几个重点概念明确下:
1.方法其实是接收者(或者说receiver)上的一个函数。特殊类型的函数罢了
2.接受者必须是内置类型或者结构体的一个值或者指针
在php中:
class person {
public function PrintName($name) {
print_r($name);
}
}
$person = new person();
$person->PrintName('咖啡色的羊驼');
在go中:
package main
import (
"fmt"
)
// 定义一个结构体,当作方法接收者
type Person struct {}
// 方法声明其实就是在函数的基础上在func后面多增加定义接收者
// func (r ReceiverType) funcName(parameters) (results)
func (p Person) PrintName(name string) {
fmt.Println(name)
}
func main() {
cbs := Person {} // 字面量的方式定义一个person类型
cbs.PrintName("咖啡色的羊驼") // 直接调用方法
}
是不是感觉很巧妙?go的方式实现了和php类一样的效果,底下可以跟一大丢函数。
面向对象的思想里头有个概念叫做继承。
php例子就不写了,直接上go,show your code:
package main
import (
"fmt"
)
type Person struct {
}
type SuperMan struct {
Person // 通过结构体内嵌包含的方式,来实现继承一样的效果
Age int
}
func (p Person) PrintName(name string) {
fmt.Println(name)
}
func (s SuperMan) PrintAge() {
fmt.Println(s.Age)
}
func main() {
cbs := SuperMan{Age:18}
cbs.PrintName("咖啡色的羊驼") // 输出"咖啡色的羊驼"
cbs.Person.PrintName("咖啡色的羊驼")// 输出"咖啡色的羊驼"
cbs.PrintAge() // 输出18
}
重载简单的说就是重新定义一个函数名相同,参数个数或者类型不同的函数,并且存在于一个类中(go可以对应与同一个接受者中)。
!!!是的,go里头没有重载!!!
重写就是重新定义一个函数名相同,参数个数和类型也相同的函数,并且存在于同一个类或者子类中(翻译到go就是同一个接受者,或者继承的接受者)。
是的,重写go有了,
但是在go中不是真正严格意义上的面向对象,只是实现方式可以类比,所以go的重写也只是类比,参数不一定要相同,因为实际上还是看调用者调的方法所属的receiver。
~上代码:
package main
import (
"fmt"
)
type Person struct {
}
type SuperMan struct {
Person // 通过结构体内嵌包含的方式,来实现继承一样的效果
Age int
}
func (p Person) PrintName(name string) {
fmt.Println(name)
}
func (s SuperMan) PrintName(name string) {
fmt.Println(name)
fmt.Println(1) // 多来一个1以示区别
}
func (s SuperMan) PrintAge() {
fmt.Println(s.Age)
}
func (s SuperMan) PrintName(name string) {
fmt.Println(name,123)
}
func main() {
cbs := SuperMan{Age:18}
cbs := SuperMan{Age:12}
cbs.Person.PrintName("咖啡色的羊驼1")// 输出"咖啡色的羊驼"
cbs.PrintName("咖啡色的羊驼2") // 输出"咖啡色的羊驼"和1
}
type Person struct {
Age float64
}
// 指针接收者
func (p *Person) AgeIncr(num float64) {
p.Age *= num
}
func main() {
cbs := &Person{Age:18}
cbs.AgeIncr(2)
fmt.Println(*cbs) // 输出 '{36}',说明初始化的值被改变了
}
!!划重点!!
1.go语言只有一种控制命令可见性(public or private)的方式:定义的时候,首字母大写就是可以从包中导出(public),反之亦然。
2.go语言中封装的单元是包,而不是类型。无论在函数内的代码,还是方法内,或者结构体内的字段对于同一个包中的所有代码都是可见的。
第一点很好理解,来一个例子,来证明一下第二点,:
type Person struct {
age float64
}
func (s Person) PrintAge() {
fmt.Println(s.age)
}
func main() {
cbs := Person{age:18}
cbs.PrintAge()
// 输出18
// 说明"方法当中可以访问结构当中的私有字段"
// go语言中封装的单元是包,而不是类型
}