go语言学习(五)——面向对象编程
主要讲的是“类”和接口&和其他传统语言不一样的地方挺多的,断断续续看了好几天
下面是我的练习代码
// 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语言中,并不需要考虑上面的问题
*/

浙公网安备 33010602011771号