主要讲的是“类”和接口&和其他传统语言不一样的地方挺多的,断断续续看了好几天
下面是我的练习代码
// GoStudy0219 project main.go /* go语言学习——面向对象编程(1) go中类型的值语义和引用语义 结构体(类)的定义和初始化 */ package main import ( "fmt" ) func main() { //几种“类”的初始化 v1 := &character{"Tom", 100, 10, 100} //这样定义出来的v1实际上时“类”的地址 v2 := new(character) // 等价于v4:=&character{} v2.name = "Judy" v2.hp = 50 v2.magic = 150 v2.attack = 30 v3 := &character{name: "Jim", hp: 150} //注意是花括号 v3.magic = 30 v3.attack = 20 fmt.Println(v1) fmt.Println(v2) fmt.Println(v3) fmt.Println("*********************") //使用类的函数 v1.addHp(600) fmt.Println(v1) fmt.Println(v1.hpIsLessThan(*v2)) fmt.Println(v2) fmt.Println("*********************") //其他类型 var v5 Age = 100 fmt.Println(v5) v5.add(10) fmt.Println(v5) v5.errorAdd(10) fmt.Println(v5) fmt.Println("*********************") //值语义和引用语义 //基本数据类型int,float之类的时值语义 //数组和切片是值语义 //map,channel和interface是引用语义 } type Age int func (this *Age) add(target Age) { *this += target } func (this Age) errorAdd(target Age) { this += target } //结构体(与其他语言中的类地位相同) type character struct { name string hp float32 attack float32 magic float32 } func (this character) hpIsLessThan(target character) bool { //this character 不会改变this target.attack = 66 return this.hp < target.hp } func (this *character) addHp(value float32) { //this *character 会改变this this.hp += value }
// GoStudy0223 project main.go /* go语言学习——面向对象编程(2) 匿名组合 可访问性 */ package main import ( "fmt" ) func main() { fmt.Println("Hello World!") var stu *student = &student{1001, *&person{"Tom", 10, true}} fmt.Println(stu) stu.greet() //匿名组合,能直接调用匿名的函数的方法 fmt.Println(stu.name) //匿名组合能够直接调用匿名函数的属性 stu.walk() //多态重载的实现 var tea *teacher = &teacher{55, "Judy", *&person{"Tom", 10, false}} fmt.Println(tea.name) } type person struct { name string age int isMan bool } func (this *person) greet() { fmt.Println("hello") } func (this *person) walk() { fmt.Println("walk slow") } type student struct { studentId int person //匿名组合 } func (this *student) walk() { //相当于多态重载,外部调用walk时不再执行匿名函数中的walk函数 this.person.walk() //根据需求,实现了“基类”的函数, fmt.Println("walk quick") } type teacher struct { teacherId int name string //person 里面的name相当于被隐藏了,外部调用teacher.name的时候,person里面的name并不会起作用 person } /* 匿名组合相当于用类型名称(去掉包名部分)作为成员变量的名字, 因此,一个类型中如果同时有类似于person和xxx.person的时候可能会报错,因此要避免这种情况 */ /* 首字母大写表示包外可访问,首字母小写,表示包外不能访问。 同一包内,不论首字母是大写还是小写都是能访问的 */
// GoStudy0224 project main.go /* go语言学习——面向对象编程(3) 接口 */ package main import ( "fmt" ) func main() { fmt.Println("Hello World!") var per = &Person{"Tom", 50} fmt.Println(per) //接口的赋值 //用对象赋值 var v1 IAdd = per //这里传入的实际上是类型的地址 v1.Add(10) fmt.Println(per) //用接口赋值 var v2 IPerson = per var v3 IWalk = v2 //函数“全”的接口可以像函数“少”的接口赋值;如果几个接口中函数相同,则这几个接口可以相互转换 v3.Walk() if v4, ok := v2.(IRead); ok { //检测,接口v2能不能转换成IRead接口 v4.Read() } if v5, ok := v2.(*Person); ok { //检测,接口v2指向的对象类型是不是Person fmt.Println(v5) } var v6 interface{} = per //interface{}是any类型,空接口 switch v7 := v6.(type) { //检测接口指向对象的类型 case int: fmt.Println(v7, "int") default: fmt.Println(v7, "other") } var v8 IPerson2 = per v8.Read() } type Person struct { name string age int } func (this *Person) Add(value int) { this.age += value } func (this *Person) Walk() { fmt.Println("walk") } func (this *Person) Speak() { fmt.Println("speak") } func (this *Person) Read() { fmt.Println("read") } //定义接口 type IWalk interface { Walk() //定义接口函数,省略func关键字 } type IRead interface { Read() } type ISpeak interface { Speak() } type IAdd interface { Add(value int) } type IPerson interface { Walk() Read() Speak() } type IPerson2 interface { //接口的组合,等同于上一个接口的写法 ISpeak IRead IWalk } /*传统语言的接口是一种契约,使用接口的类必须实现接口的所有方法,不同命名空间下的同名接口也被视为两个不同的接口 eg. C# java等需要考虑定义什么接口,在哪个类里面实现接口 go语言中,并不需要考虑上面的问题 */