文章目录
go语言面向对象
GO语言中没有类(class)的概念,但是我们可以将结构体比作为类,因为在结构体中可以添加属性(成员),方法(函数)。
- c语言是面向过程编程
- c++ 是面向对象编程
- go语言是面向接口编程
面向对象的三要素: 封装、继承、多态
封装
go语言没有class 关键字,可以使用结构体代替
go
//定义结构体
Type Student struct{
name string
age int
}
//添加成员方法
func (this*Student)Init(){
this.name = "wuyou"
this.age = 18
}
func (this*Student)Print(){
fmt.Println(this.name, this.age)
}
//测试
func main(){
var stu Student
stu.Init()
stu.Print()
}
继承
- 有名继承
- 在子类的结构体中定义一个父类对象变量
- 如果子类和父类不在一个包中,子类只能继承父类的公有成员**(首字母大写的成员变量和 方法)**
- 匿名继承
- 如果子类和父类有同名属性的成员变量,直接赋值会采用就近原则
- 如果子类和父类有同名成员方法,直接使用会采取就近原则
在继承的时候,如果需要跨包使用,成员变量首字母大写的属于公有继承,否则类似私有继承
有名继承
go
type Person struct{
High float64
weight float64
}
type Student struct{
name string
age int
//有名继承
p Persion
}
func main(){
s := Student{"wuyou",18,Persion{180.0, 60.0}};
s.Print();
}
匿名继承
- 匿名继承会把父类的属性直接加载到子类上
- 给父类成员赋值的时候可以加上类名
go
type Person struct{
High float64
weight float64
}
type Student struct{
name string
age int
High float64
//匿名继承
Persion
}
func main(){
//带父类对象的初始化,如果是匿名继承,不能使用带属性的初始化
st := Student{"wuyou",18,test.Persion(High:168.0,weight:62.0)}
s := Student{name:"wuyou",age:18}
s.High = 180;
s.weight = 60.0
//如果子类和父类有同名属性的成员变量,直接赋值会采用就近原则
//给父类成员赋值的时候可以加上类名
s.Persion.High = 181.1
Println(s);
}
多态
go语言借助interface实现了多态
多态三要素
-
父类中有虚函数
-
子类重写了父类的虚函数
-
父类指针指向子类对象
go
//这里只做声明,不实现 ,有点像c++中的纯虚函数
type MyInter interface {
//相当于纯虚函数
Study(string)
}
type Xiaoming struct {}
//这里的this* 只是一种习惯而已,也可以写其他的,go语言中并没有this指针这个概念
func(this*Xiaoming)Study(object string){
fmt.Println("xiaoming 在学习"+object)
}
type Xiaowang struct {}
func (this*Xiaowang)Study(object string){
fmt.Println("xiaowang 在学习"+object)
}
//多态三要素
//有一个父类指针,指向了子类对象
func WhoAreYou(man MyInter){
man.Study("语文")
}
func main() {
var wang Xiaoming
WhoAreYou(&wang)
}
- 如果一个结构体完全实现了interface中的方法,这个结构体继承于这个interface
空接口
- 如果interface 中没有函数定义,那么这个interface就是空接口
- 空接口是多有类型的父类,也是个万能类
- interface 结合...使用,那么函数的参数长度不确定,参数类型也不确定
- 通过反射打印出每个空接口参数的类型
- 也可以使用断言来打印;断言可以返回一个值也可以返回两个值,第一个值是实参,第二个值就是bool类型,如果断言成功,返回true,断言失败,返回false
- 使用断言的时候不建议使用一个返回值的断言,因为断言失败的时候会抛出异常(可能会引起程序崩溃)
go
//interface 结合...使用,那么函数的参数长度不确定,参数类型也不确定
func EchoContent(content ...interface{}){
fmt.Println(content)
}
func EchoContent_1(content interface{}){
fmt.Println(content)
}
func main(){
EchoContent(123);
EchoContent("wuyou");
EchoContent(true);
}
go
func EchoContent(content ...interface{}){
for i:=0; i < len(content); i++{
//通过反射打印出每个参数的类型
fmt.Println(reflect.TypeOf(content[i]))
//断言
a := content[i].(int)
fmt.Println(a);
//返回连个值的断言
b,ok :=content[i].(int)
if ok{
//执行数据处理
}
}
};
异常处理
在go语言中只有两种异常处理
- panic 会调用底层的程序栈(导致程序终止)
- error
- error的空值是nil
- 在go语言标准库中定义了一个interface类型的error,并且在标准库中定义一个结构体实现了error中的方法,这个结构体和error具备继承关系
- 在错误提示中error提示的错误不会导致程序崩溃,panic会直接导致程序终止,所以error在开发中比较的常用
go
func TestErr(a interface{}) error {
b,ok := a.(int)
if !ok{
//一般创建error类型的时候使用errors.New(),和panic的区别是panic会导致程序的崩溃
//error提示错误之后,程序会继续执行
return errors.New("类型错误")
}
fmt.Println(b)
return nil
}