什么是方法
<h1>单元目标</h1>
<ul>
<li>结构体类型调用方法</li>
<li>任意类型方法</li>
<li>函数与方法的区别</li>
</ul>
<h2>什么是方法</h2>
<p>在Go语言中方法和函数类似,也可以认为方法是特殊类型的函数,只不过方法限制了接收者,方法也可以说是包含了接收者的函数。</p>
<p><img src="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/6/17/172c20329f13590f~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp" alt="" /></p>
<p><img src="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/6/19/172c83df62f1f01a~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp" alt="" /></p>
<h2>结构体类型调用方法</h2>
<pre><code>package main
import (
"fmt"
)
func main() {
//使用Role结构体创建一个角色代表任我行
rwx := Role{"任我行", "吸星大法", 10, 9.9}
rwx.Kungfu()//调用这个结构体的方法。
}
//创建一个结构体代表人物角色--任我行
type Role struct {
Name string //姓名
Ability string //技能
Level int //级别
Kill float64 //杀伤力
}
//创建一个方法,只要是Role结构体就能调用。
func (r Role) Kungfu() {
fmt.Printf("我是:%s,我的武功:%s,已经练到%d级了,杀伤力%.1f\n", r.Name, r.Ability, r.Level, r.Kill)
}</code></pre>
<p><img src="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/6/19/172c82bdea876f3a~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp" alt="" /></p>
<p><img src="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/6/18/172c7a932df412c9~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp" alt="" /></p>
<h2>指针类型方法</h2>
<p>方法的接收者可以是结构体类型,也可以是一个值,或者是一个指针类型。</p>
<pre><code>package main
import (
"fmt"
)
func main() {
rwx := &Role{"任我行", "吸星大法", 8, 10}
rwx.Kungfu() //使用Role该类型的指针调用方法
zwj := &Role{"张无记", "九娘神功", 9, 12}
zwj.Kungfu2() //调用指针类型方法
}
//创建一个结构体代表人物角色--任我行或者张无忌
type Role struct {
Name string //姓名
Ability string //技能
Level int //级别
Kill float64 //杀伤力
}
func (r Role) Kungfu() {
fmt.Printf("我是:%s,我的武功:%s,已经练到%d级了,杀伤力%.1f\n", r.Name, r.Ability, r.Level, r.Kill)
}
//指针类型方法
func (r *Role) Kungfu2() {
fmt.Printf("我是:%s,我的武功:%s,已经练到%d级了,杀伤力%.1f\n", r.Name, r.Ability, r.Level, r.Kill)
}</code></pre>
<p><img src="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/6/18/172c8170ee80042b~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp" alt="" /></p>
<h2>任意类型方法</h2>
<p>在Go语言中,使用<code>type</code>关键字可以定义出新的自定义类型,有了自定义类型之后我们就可以为自定义类型添加各种方法了。</p>
<p><img src="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/6/20/172cf3ce265507e4~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp" alt="" /></p>
<pre><code>package main
import (
"fmt"
)
// 将好家伙 定义为int类型
type Haojiahuo int
// 使用Clear方法将Haojiahuo的所有值清空
func (h Haojiahuo) Clear() bool {
h = 0
return h == 0
}
// 使用Add方法给Haojiahuo增加值
func (h Haojiahuo) Add(num int) int {
return int(h) + num
}
func main() {
var h Haojiahuo
fmt.Println(h.Clear()) //调用清空方法
fmt.Println(h.Add(2)) //调用添加方法加2
fmt.Println(h.Clear()) //调用清空方法
fmt.Println(h.Add(6)) //调用添加方法加6
fmt.Println(h.Clear()) //调用清空方法
fmt.Println(h)
}</code></pre>
<p><code>函数与方法的区别</code></p>
<ul>
<li>方法限制某个类别的行为,需要指定调用者。函数是一段独立的功能代码,可以直接调用。</li>
<li>方法名称可以相同,只要接收者不同就可以,函数命名上不能冲突。</li>
</ul>
<h2>Go语言实现面向对象</h2>
<p>其实在Go语言中是没有面向对象的,但是Go语言的语法设计,我们可以借助结构体,方法,接口的实现,来模拟其他语言中的面向对象的概念。首先了解一下什么是面向对象,面向对象中的三大特征是:</p>
<ul>
<li><code>封装</code> 在意义上是把许多客观的事物封装成一个抽象的类,把自己的属性 方法只让可信的对象操作。</li>
<li><code>继承</code> 子类可以访问父类的属性和方法,子类也可以拥有自己的属性和方法。子类可以重写父类的方法。</li>
<li><code>多态</code> 是指一个程序中同名的方法共存的情况,调用者只需使用同一个方法名,系统会根据不同情况,调用相应的不同方法,从而实现不同的功能。多态性又被称为“一个名字,多个方法”。</li>
</ul>
<h3>1,使用结构体来实现封装</h3>
<p>Go语言中没有像java或者.net中的class类,不过可以把struct结构体看成一个类,结构体如果用面向对象的思维来理解,结构体把字段封装到一起,数据被保护在结构体内部,程序需要访问字段的时候,需要通过结构体来访问。</p>
<p><img src="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/6/20/172cf6c3c1c7341b~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp" alt="" /></p>
<pre><code>package main
import (
"fmt"
)
// 定义结构体实现封装
type Haojiahuo struct {
Name string
Age int
}
//使用NewPerson方法创建一个对象
func NewPerson(name string) *Haojiahuo {
return &Haojiahuo{
Name: name,
}
}
// 使用SetAge方法设置结构体成员的Age
func (h *Haojiahuo) SetAge(age int) {
h.Age = age
}
// 使用GetAge方法获取成员现在的Age
func (h *Haojiahuo) GetAge() int {
return h.Age
}
func main() {
//创建一个对象
h := NewPerson("好家伙")
h.SetAge(18) //访问封装的方法设置年龄
fmt.Println(h.Name, h.GetAge()) //使用对象封装的方法获取年龄
}</code></pre>
<h3>2,继承的实现</h3>
<p>继承可以解决代码复用的问题,结构体内嵌套一个匿名结构体,也可以嵌套多层结构体。</p>
<p><img src="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/6/20/172cfa84486a7dd5~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp" alt="" /></p>
<p><img src="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/6/20/172cfd1681e247ba~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp" alt="" /></p>
<pre><code>package main
import (
"fmt"
)
// 创建一个结构体起名 Ouyangcrazy 代表父类
type Ouyangcrazy struct {
Name string
Age int
Ability string
}
//创建一个结构体代表子类
type YangGuo struct {
Ouyangcrazy //包含父类所有属性
Address string //单独子类有的字段
}
// 父类的方法
func (o *Ouyangcrazy) ToadKongfu() {
fmt.Println(o.Name, "的蛤蟆功!")
}
//子类的方法
func (y *YangGuo) NewKongfu() {
fmt.Println(y.Name, "子类自己的新功夫!")
}
//子类重写父类的方法
// func (y *YangGuo) ToadKongfu() {
// fmt.Println(y.Name, "的新蛤蟆功!")
// }
func main() {
o := &Ouyangcrazy{Name: "欧阳疯", Age: 70} //创建父类
o.ToadKongfu() //父类对象访问父类方法
y := &YangGuo{Ouyangcrazy{Name: "杨过", Age: 18}, "古墓"} //创建子类
fmt.Println(y.Name) //子类对象访问父类中有的字段
fmt.Println(y.Address) //子类访问自己的字段
y.ToadKongfu() //子类对象访问父类方法
y.NewKongfu() //子类访问自己的方法
//y.ToadKongfu() //如果存在自己的方法 访问自己重写的方法
}</code></pre>
<p><img src="https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/6/20/172cfc64058e4c1c~tplv-t2oaga2asx-zoom-in-crop-mark:3024:0:0:0.awebp" alt="" /></p>