go语言面向对象 | 青训营笔记
这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天
1.面向对象结构体
面向对象需要设置结构体,即面向对象中的类,定义格式类似为c语言的结构体;然后单独写其实现方法,定义方法时需要加参数this 类名来确定为此类的方法。类名、属性名、⽅法名 ⾸字⺟⼤写表示对外(其他包) 可以访问,否则只能够在本包内访问。
type Hero struct {
Name string
Ad int
Level int
}
func (this Hero) Show() {
fmt.Println(this)
}
func (this Hero) GetName() {
fmt.Println("Name=", this.Name)
}
2.值传递和引用传递
如果在this传参数中按以上代码来实现,则只能进行值传递,不能更改此类的实际数据,需要加*,指针类型变量。一个方法的接收者是指针类型,一个方法的接收者是值类型。
package main
import "fmt"
//定义一个结构体
type T struct {
name string
}
func (t T) method1() {
t.name = "new name1"
}
func (t *T) method2() {
t.name = "new name2"
}
func main() {
t := T{"old name"}
fmt.Println("method1 调用前 ", t.name)
t.method1()
fmt.Println("method1 调用后 ", t.name)
fmt.Println("method2 调用前 ", t.name)
t.method2()
fmt.Println("method2 调用后 ", t.name)
3.继承
跟其他语言一样,先定义父类的结构体和其方法,然后定义子类的时候,需要在结构体声明一下父类,子类中可以重新定义父类的方法,也可以继续添加新的方法。当给子类赋值时有两种赋值方法,1为在定义赋值时需要在大括号中添加子类的属性;2为直接声明一个类名,然后分别添加其属性值
type Human struct {
name string
sex string
}
func (this *Human) Eat() {
fmt.Println("Human.Eat().....")
}
func (this *Human) Walk() {
fmt.Println("Human.Walk().....")
}
type SuperMan struct {
Human //SuperMan类继承了Human类的方法
level int
}
//重定义父类的方法Eat()
func (this *SuperMan) Eat() {
fmt.Println("SuperMan.Eat().....")
}
//子类的新方法
func (this *SuperMan) Fly() {
fmt.Println("SuperMan.Fly()...")
}
func main() {
h := Human{"zhangsan", "female"}
h.Eat()
h.Walk()
//定义一个子类对象
//第一种赋值方法
//s := SuperMan{Human{"li4", "female"}, 88}
//第二种赋值方法
var s SuperMan
s.name = "li4"
s.sex = "female"
s.level = 88
s.Walk() //父类的方法
s.Eat() //子类的方法
s.Fly() //子类的方法
4.多态
多态即指将一个对象变量引用多种实际类型,多态需要有三种必要条件:
- 有若干子类继承同一个父类;
- 子类重写了父类中的方法;
- 父类的引用指向了子类对象
同一个类型的对象执行同一个行为,会表现出不同的行为特征。又由于多态更加侧重于行为多态,因此变量的调用和方法调用是不同的。在实现时可以使用通用数据类型interface类型,该类型为指针型变量,定义结构体父类需要定义其属性和定义其方法,实现了父类全部接口的方法的类是子类,具体定义时,使用了父类的类型变量,声明数据,然后在使用子类的类名来进行传参,该父类调用方法时就显示多态性。
package main
import (
"fmt"
)
// interface本质是一个指针
type AnimalIf interface {
Sleep()
GetColor() string //获取动物的颜色
GetType() string //获取动物的种类
}
// 具体的类
type Cat struct {
color string
}
// 一个类重写了所有接口方法,表示一个具体的类
func (this *Cat) Sleep() {
fmt.Println("Cat is Sleep")
}
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("DOg is Sleep")
}
func (this *Dog) GetColor() string {
return this.color
}
func (this *Dog) GetType() string {
return "Dog"
}
func main() {
var animal AnimalIf //接口的数据类型,父类指针
animal = &Cat{"green"}
animal.Sleep() //调用的就是cat的sleep方法
animal = &Dog{"yellow"}
animal.Sleep() //调用的dog的sleep方法 多态表现
}
5.interface和断言机制
Golang的语言中提供了断言的功能。golang中的所有程序都实现了interface{}的接口,这意味着,所有的类型如string,int,int64甚至是自定义的struct类型都就此拥有了interface{}的接口,这种做法和java中的Object类型比较类似。那么在一个数据通过func funcName(interface{})的方式传进来的时候,也就意味着这个参数被自动的转为interface{}的类型。
类型断言有以下几种形式:
- 直接断言使用:
var a interface{}
fmt.Println("Where are you,Jonny?", a.(string))
但是如果断言失败一般会导致panic的发生。所以为了防止panic的发生,我们需要在断言前进行一定的判断,如果断言失败,那么ok的值将会是false,但是如果断言成功ok的值将会是true,同时value将会得到所期待的正确的值。
- 配合switch使用