注:安装教程
上一篇
Go语言面向对象编程
二、面向对象编程
1、类和方法
1.1、简单实例
func main(){//第一种调用方式a.Less(b)var a Integer =1println("a是否大于b:", a.Less(2))//第二种调用方式Less(a,b)println("a是否大于b:",Less(2,1))}
type Integer int //定义一个Integer类型/*
定义比较函数:第一种写法
*/func(a Integer)Less(b Integer) bool {return a < b
}/*
定义比较函数:第二种写法
*/
func Less(a Integer, b Integer) bool {return a < b
}
1.2、指针
1、Go语言中的面向对象最为直观,也无需支付额外的成本。如果要求对象必须以指针传递,这有时会是个额外成本,因为对象有时很小(比如4字节),用指针传递并不划算。
只有在你需要修改对象的时候,才必须用指针。它不是Go语言的约束,而是一种自然约束。举个例子
func main(){/*
函数两种区别:
打印结果如下:
LessOne:a= 3
a=: 1
LessOne:a= 4
a=: 4
总结:
加*表示指针,指向对象a可以修改a的值
不加*星号,方法内a修改,外部不修改
*///第一种var a Integer =1
a.LessOne(2)println("a=:", a)//输出a=: 1//第二种
a.LessTwo(3)println("a=:", a)//输出a=: 4}
type Integer int //定义一个Integer类型/*
定义相加函数:第一种写法
*/func(a Integer)LessOne(b Integer){
a += b
println("LessOne:a=", a)}/*
定义相加函数:第二种写法
*/func(a *Integer)LessTwo(b Integer){*a += b
println("LessOne:a=",*a)}
2、引用类型
如果b的修改不会影响a的值,那么此类型属于值类型。如果会影响a的值,那么此类型是引用类型。
func main(){/**
数组类型赋值b=a是将内容完全复制,如果想表达引用使用指针。
例:修改b,a不会改变 修改c,a会改变
*/var a =[3]int{1,2,3}var b = a
b[1]++
fmt.Println(a, b)//输出:[1 2 3] [1 3 3]var c =&a
c[1]++
fmt.Println(a,*c)//输出:[1 3 3] [1 3 3]}
1.3、结构体定义和初始化
- 结构体=类+方法
- 在Go语言中,未进行显式初始化的变量都会被初始化为该类型的零值,例如bool类型的零值为false,int类型的零值为0,string类型的零值为空字符串。
- 在Go语言中没有构造函数的概念,对象的创建通常交由一个全局的创建函数来完成,以NewXXX来命名,表示“构造函数”:
func main(){//初始化
u1 :=new(User)//输出:&{ }
u2 := User{}//输出:{ }
u3 := User{"binshao","18","男"}//输出:{binshao 18 男}
u4 := User{age:"18", name:"liming"}//输出:{liming 18 }//使用构造函数初始化
u5 :=NewUser("zhangsan","12","女")//输出:&{zhangsan 12 女}
fmt.Println(u1)
fmt.Println(u2)
fmt.Println(u3)
fmt.Println(u4)
fmt.Println(u5)}
type User struct {//自定义类
name string
age string
sex string
}func(u *User)getIntroduce() string {//定义类中的方法return"名字:"+ u.name +" 年龄:"+ u.age +" 性别:"+ u.sex
}
func NewUser(name, age, sex string)*User {//定义类的构造函数return&User{name, age, sex}}
1.4、可见性
大写字母开头,表示可以被其他包访问到,小写字母只能本包访问。
例如:User类型的成员变量就全部被导出了,可以被所有其他引用了User所在包的代码访问到。
成员方法的可访问性遵循同样的规则,User中getUser()方法只能在该类型的包内使用
type User struct {
Name string
Sex string
}func(u *User)getUser() string {return"姓名:"+ u.Name +" 性别:"+ u.Sex
}
注意:Go语言中符号的可访问性是包一级的而不是类型一级的。在上面的例子中,尽管getUser是User的内部方法,但同一个包中的其他类型也都可以访问到它。这样的可访问性控制很粗旷,很特别,但是非常实用。如果Go语言符号的可访问性是类型一级的,少不了还要加上friend这样的关键字,以表示两个类是朋友关系,可以访问彼此的私有成员。
2、接口
2.1、接口定义与实现
在Go语言中,一个类只需要实现了接口要求的所有函数,我们就说这个类实现了该接口
/*
例如:
IUser、IGetName、IGetSex、IGetAge中的方法被User全部实现
*/
func main(){/*
尽管User类并没有从这些接口继承,甚至不知道这些接口的存在,但是User类实现了
这些接口,可以进行赋值,如下:
*/var user1 IUser =new(User)var user2 IGetName =new(User)var user3 IGetAge =new(User)var user4 IGetSex =new(User)
fmt.Println(user1.getName())
fmt.Println(user2.getName())
fmt.Println(user3.getAge())
fmt.Println(user4.getSex())}
type User struct {
Name string
age int
sex string
}func(u *User)getName()(name string, err error){return u.Name, nil
}func(u *User)getAge()(age int, err error){return u.age, nil
}func(u *User)getSex()(sex string, err error){return u.sex, nil
}
type IUser interface{getName()(name string, err error)getAge()(age int, err error)getSex()(sex string, err error)}
type IGetName interface{getName()(name string, err error)}
type IGetAge interface{getAge()(age int, err error)}
type IGetSex interface{getSex()(sex string, err error)}
2.2、接口赋值
接口赋值
1、将对象实例赋值给接口;
2、将一个接口赋值给另一个接口。
func main(){
user := User{"wang",19,"男"}/*
对象赋值接口
结论:实例赋值接口是使用"&"
*/var user1 IUser = user //报错var user2 IUser =&user //成功/*
接口赋值接口
结论:一个接口赋值给另一个接口时,必须实现另一个接口的所有方法
*/var user3 IUser =&user //成功var user4 IGetName = user3 //成功var user5 IUser = user4 //报错var user6 IGetAge = user4 //报错}
2.3、接口类型
在Go语言中,还可以更加直截了当地询问接口指向的对象实例的类型,例如
func main(){var v interface{}="字符串"switch v.(type){case int:println("int类型")case string:println("string类型")default:println("类型缺省")}}
版权归原作者 binshao.wang 所有, 如有侵权,请联系我们删除。