面向对象三大特征:封装、继承、多态。
方法
假设有两个方法,一个方法的接收者,是指针类型,一个方法的接收者是值类型,
那么:
对于值传递的变量和指针类型的变量,这两个方法的区别
如果这两个方法是为了实现一个接口,那么这两个方法都可以调用吗?
如果方法是嵌入到其他结构体中的,那么上面两种情况又是怎样的?
首先解决第一个问题:
对于值传递的变量和指针类型的变量,这两个方法的区别?
如下图测试示意:
很明显看出值传递和引用的区别。
封装
那么现在进入结构体的定义使用
定义
// 定义一个结构体
type Hero struct {
Name string ``
Age int
Sex int
}
上述就是定义了一个结构体,那怎么使用呢
package main
import "fmt"
type Person struct {
Name string
Age int
}
func main() {
var p Person
p.Name = "张三"
var p2 Person = Person{"lisi", 15}
p3 := Person{"wangwu", 15}
fmt.Println(p, p2, p3)
}
如图运行:
根据结构体来进一步构建类
其实类就是由结构体进一步绑定方法实现的。
package main
import "fmt"
// 定义一个结构体
type Hero struct {
Name string ``
Age int
Sex int
}
func (hero Hero) SetName(name string) {
//hero是调用方法的一个副本
hero.Name = name
}
func (hero Hero) GetName() string {
return hero.Name
}
func (hero Hero) Show() {
fmt.Println("hero = ", hero)
}
func main() {
var hero Hero = Hero{"赵六", 18, 1}
hero.Show()
hero.SetName("王五")
hero.Show()
}
明明在主函数进行了修改,但还是属性没有发送变化,是为什么呢?
其实是在给结构体挂上方法的时候,使用的是值传递
hero是一个方法的对象的一个副本
那么怎么解决呢?(使用指针)
package main
import "fmt"
// 定义一个结构体
type Hero struct {
Name string ``
Age int
Sex int
}
func (hero *Hero) SetName(name string) {
//hero是调用方法的一个副本
hero.Name = name
}
func (hero *Hero) GetName() string {
return hero.Name
}
func (hero *Hero) Show() {
fmt.Println("hero = ", *hero)
}
func main() {
var hero Hero = Hero{"赵六", 18, 1}
hero.Show()
hero.SetName("王五")
hero.Show()
}
如图:属性修改成功
注意:
类名首字母大写,标识其他包也能够访问
同理,属性、方法 大小写也是标识是否可以被外部访问
继承
语法就是在子类中添加上父类即可。如下代码:
package main
import "fmt"
type Person struct {
Name string
Age int
}
func (this *Person) Eat() {
fmt.Println("Person Eat()...")
}
func (this *Person) Walk() {
fmt.Println("Person Walk()...")
}
type SuperMan struct {
Person //标识SuperMan继承了Person类的方法
level int
}
// 重定义父类的方法Eat()
func (this *SuperMan) Eat() {
fmt.Println("SuperMan Eat()...")
}
// 子类的新方法
func (this *SuperMan) Fly() {
fmt.Println("SuperMan Fly()...")
}
func main() {
p := Person{"zhangsan", 18}
p.Eat()
p.Walk()
s := SuperMan{Person{"张三", 18}, 0}
s.Eat()
s.Fly()
s.Walk()
var s1 SuperMan
s1.Name = "lisi"
}
多态(依靠interface接口)
要素:
- 父类(接口)
- 子类(实现了父类的全部结构)
- 父类类型的变量(指针)指向子类的具体变量
package main
import "fmt"
type AnimalIF interface {
Sleep() //让动物睡觉
GetColor() string //获取动物颜色
GetType() string //获取动物种类
}
// 具体的类
type Cat struct {
//AnimalIF 继承接口没必要,只要定义方法实现就可以了,相当于继承了
color string
}
func (this *Cat) Sleep() {
fmt.Println("小猫睡觉")
}
func (this *Cat) GetColor() string {
return this.color
}
func (this *Cat) GetType() string {
return "Cat"
}
type Dog struct {
color string
}
func (this *Dog) Sleep() {
fmt.Println("小狗睡觉")
}
func (this *Dog) GetColor() string {
return this.color
}
func (this *Dog) GetType() string {
return "Dog"
}
func showAnimal(animal AnimalIF) {
animal.Sleep()
fmt.Println(animal.GetColor())
fmt.Println(animal.GetType())
}
func main() {
var cat AnimalIF
cat = &Cat{"yellow"}
var dog AnimalIF = &Dog{"blue"}
showAnimal(cat)
showAnimal(dog)
}