Go面向对象(三)
anbylau2130 · · 2982 次点击 · · 开始浏览go语言中的大多数类型都是值予以,并且都可以包含对应的操作方法,在需要的时候你可以给任意类型增加新方法。二在实现某个接口时,无需从该接口集成,只需要实现该接口要求的所有方法即可。任何类型都可以被any类型引用。any类型是空接口 interface{}
package mainimport("fmt")func main(){person.Go2School()}func (ps Person)Go2School(){fmt.Println("go to school")}
- 基本类型,如byte、int、bool、float32、float64和string等;
复合类型,如数组(array)、结构体(struct)和指针(pointer)等。
值语义和引用语义
a :=10
b := a
b = b +1
fmt.Println(b)
fmt.Println(a)
输出:11,10
c :=10
d :=&c
*d +=1
fmt.Println(c)
fmt.Println(*d)
输出:11,11
Go语言中有4个类型比较特别,看起来像引用类型接口(interface):对一组满足某个契约的类型的抽象
结构体 定义:type Rectstruct{x, y float64width, height float64}初始化rect1 :=new(Rect)rect2 :=&Rect{}rect3 :=&Rect{0,0,100,200}rect4 :=&Rect{width:100, height:200}
构造函数
package main
//person类
type Personstruct{
Namestring
Ageint
Sexstring
}
//person构造函数
func NewPerson(name string, sex string, age int)*Person{
return&Person{Name: name,Sex: sex,Age: age}
}
//person类ResetName1方法 (传值)
func (ps Person)ResetName1(name string){
ps.Name= name
}
//person类ResetName1方法 (传址)
func (ps *Person)ResetName2(name string){
ps.Name= name
}
//student类
type Studentstruct{
Classstring
Gradestring
*Person
}
//student构造函数
func NewStudent(name string, sex string, age int,classstring, grade string)*Student{
return&Student{Person:NewPerson(name, sex, age),Class:class,Grade: grade}
}
匿名组合:类的继承是使用了匿名组合的方式 package maintype Personstruct{NamestringAgeintSexstring}//构造函数func NewPerson(name string, sex string, age int)*Person{return&Person{Name: name,Sex: sex,Age: age}}func (ps Person)ResetName1(name string){ps.Name= name}func (ps *Person)ResetName2(name string){ps.Name= name}//继承自Persontype Studentstruct{ClassstringGradestringPerson//或者*Person}这样Student就继承自了Person类
可见性 要使某个符号对其他包(package)可见(即可以访问),需要将该符号定义为以大写字母开头
type Rectstruct{X, Y float64Width,Height float64}
这样,Rect类型的成员变量就全部被导出了,可以被所有其他引用了Rect所在包的代码访问到。
func (r *Rect) area() float64 {return r.Width * r.Height}这样,Rect的area()方法只能在该类型所在的包内使用。
Go语言中符号的可访问性是包一级的而不是类型一级的
- 入侵接口c#和Java中的接口时入侵是接口
- 非入侵接口go的接口是非入侵式接口
type File struct {// ...}func (f *File) Read(buf []byte) (n int, err error)func (f *File) Write(buf []byte) (n int, err error)func (f *File) Seek(off int64, whence int) (pos int64, err error)func (f *File) Close() error
type IFile interface {
Read(buf []byte) (n int, err error)Write(buf []byte) (n int, err error)Seek(off int64, whence int) (pos int64, err error)Close() error
}type IReader interface {Read(buf []byte) (n int, err error)}type IWriter interface {Write(buf []byte) (n int, err error)}type ICloser interface {Close() error}
var file1 IFile = new(File)var file2 IReader = new(File)var file3 IWriter = new(File)var file4 ICloser = new(File)
其一,Go语言的标准库,再也不需要绘制类库的继承树图。你一定见过不少C++、Java、C#类库的继承树图。在Go中,类的继承树并无意义,你只需要知道这个类实现了哪些方法,每个方法是啥含义就足够了。其二,实现类的时候,只需要关心自己应该提供哪些方法,不用再纠结接口需要拆得多细才合理。接口由使用方按需定义,而不用事前规划。其三,不用为了实现一个接口而导入一个包,因为多引用一个外部的包,就意味着更多的耦合。接口由使用方按自身需求来定义,使用方无需关心是否有其他模块定义过类似的接口
- 将对象实例赋值给接口;
- 将接口实例赋值给接口;
//对象赋值给接口var interfaces IStudent=NewStudent("Jessica","male",18,"class1","grade1")interfaces.Go2School()
package one
type ReadWriterinterface{
Read(buf []byte)(n int, err error)
Write(buf []byte)(n int, err error)
}
package two
type IStreaminterface{
Write(buf []byte)(n int, err error)
Read(buf []byte)(n int, err error)
}
任何实现了one.ReadWriter接口的类,均实现了two.IStream; 任何one.ReadWriter接口对象可赋值给two.IStream,反之亦然; 在任何地方使用one.ReadWriter接口与使用two.IStream并无差异。
var file1 two.IStream=new(File)
var file2 one.ReadWriter= file1
var file3 two.IStream= file2
type Writer interface {Write(buf []byte) (n int, err error)}
var file1 two.IStream = new(File)var file4 Writer = file1
// OOPTest project main.go
package main
type IStudentinterface{
Go2School()
}
type IPersoninterface{
Speak(word string)
Eat(food string)
}
func main(){
//std := NewStudent("Jessica", "male", 18, "class1", "grade1")
//psn := NewPerson("James", "female", 20)
//语句switch中的value必须是接口类型,变量str的类型为转换后的类型。/
varIStdinterface{}=NewStudent("Jessica","male",18,"class1","grade1")
switch per :=IStd.(type){
caseIStudent:
per.Go2School()
caseIPerson:
per.Eat("pig")
}
}类型断言
// OOPTest project main.go
package main
type IStudentinterface{
Go2School()
}
type IPersoninterface{
Speak(word string)
Eat(food string)
}
func main(){
//std := NewStudent("Jessica", "male", 18, "class1", "grade1")
//psn := NewPerson("James", "female", 20)
//语句switch中的value必须是接口类型,变量str的类型为转换后的类型。
varIStdinterface{}=NewStudent("Jessica","male",18,"class1","grade1")
//switch per := IStd.(type) {
//case IStudent:
// per.Go2School()
//case IPerson:
// per.Eat("pig")
//}
//上面的转换有一个问题,如果该值不包含一个字符串,则程序会产生一个运行时错误。为了避免这个问题,可以使用"comma, ok"的习惯用法来安全地测试值是否为一个字符串:
if types, ok :=IStd.(IStudent); ok {
types.Go2School()
}elseif types, ok :=IStd.(IPerson); ok {
types.Eat("pig")
}
}
接口组合:接口的继承
type IStudentinterface{Go2School()}type IPersoninterface{Speak(word string)Eat(food string)}type Animalinterface{IPersonIStudent}
var v1 interface{}=1// 将int类型赋值给interface{}var v2 interface{}="abc"// 将string类型赋值给interface{}var v3 interface{}=&v2 // 将*interface{}类型赋值给interface{}var v4 interface{}=struct{ X int}{1}var v5 interface{}=&struct{ X int}{1}
func Printf(fmt string, args ...interface{})func Println(args ...interface{})
有疑问加站长微信联系(非本文作者)
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
关注微信- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码` - 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传
收入到我管理的专栏 新建专栏
go语言中的大多数类型都是值予以,并且都可以包含对应的操作方法,在需要的时候你可以给任意类型增加新方法。二在实现某个接口时,无需从该接口集成,只需要实现该接口要求的所有方法即可。任何类型都可以被any类型引用。any类型是空接口 interface{}
package mainimport("fmt")func main(){person.Go2School()}func (ps Person)Go2School(){fmt.Println("go to school")}
- 基本类型,如byte、int、bool、float32、float64和string等;
复合类型,如数组(array)、结构体(struct)和指针(pointer)等。
值语义和引用语义
a :=10
b := a
b = b +1
fmt.Println(b)
fmt.Println(a)
输出:11,10
c :=10
d :=&c
*d +=1
fmt.Println(c)
fmt.Println(*d)
输出:11,11
Go语言中有4个类型比较特别,看起来像引用类型接口(interface):对一组满足某个契约的类型的抽象
结构体 定义:type Rectstruct{x, y float64width, height float64}初始化rect1 :=new(Rect)rect2 :=&Rect{}rect3 :=&Rect{0,0,100,200}rect4 :=&Rect{width:100, height:200}
构造函数
package main
//person类
type Personstruct{
Namestring
Ageint
Sexstring
}
//person构造函数
func NewPerson(name string, sex string, age int)*Person{
return&Person{Name: name,Sex: sex,Age: age}
}
//person类ResetName1方法 (传值)
func (ps Person)ResetName1(name string){
ps.Name= name
}
//person类ResetName1方法 (传址)
func (ps *Person)ResetName2(name string){
ps.Name= name
}
//student类
type Studentstruct{
Classstring
Gradestring
*Person
}
//student构造函数
func NewStudent(name string, sex string, age int,classstring, grade string)*Student{
return&Student{Person:NewPerson(name, sex, age),Class:class,Grade: grade}
}
匿名组合:类的继承是使用了匿名组合的方式 package maintype Personstruct{NamestringAgeintSexstring}//构造函数func NewPerson(name string, sex string, age int)*Person{return&Person{Name: name,Sex: sex,Age: age}}func (ps Person)ResetName1(name string){ps.Name= name}func (ps *Person)ResetName2(name string){ps.Name= name}//继承自Persontype Studentstruct{ClassstringGradestringPerson//或者*Person}这样Student就继承自了Person类
可见性 要使某个符号对其他包(package)可见(即可以访问),需要将该符号定义为以大写字母开头
type Rectstruct{X, Y float64Width,Height float64}
这样,Rect类型的成员变量就全部被导出了,可以被所有其他引用了Rect所在包的代码访问到。
func (r *Rect) area() float64 {return r.Width * r.Height}这样,Rect的area()方法只能在该类型所在的包内使用。
Go语言中符号的可访问性是包一级的而不是类型一级的
- 入侵接口c#和Java中的接口时入侵是接口
- 非入侵接口go的接口是非入侵式接口
type File struct {// ...}func (f *File) Read(buf []byte) (n int, err error)func (f *File) Write(buf []byte) (n int, err error)func (f *File) Seek(off int64, whence int) (pos int64, err error)func (f *File) Close() error
type IFile interface {
Read(buf []byte) (n int, err error)Write(buf []byte) (n int, err error)Seek(off int64, whence int) (pos int64, err error)Close() error
}type IReader interface {Read(buf []byte) (n int, err error)}type IWriter interface {Write(buf []byte) (n int, err error)}type ICloser interface {Close() error}
var file1 IFile = new(File)var file2 IReader = new(File)var file3 IWriter = new(File)var file4 ICloser = new(File)
其一,Go语言的标准库,再也不需要绘制类库的继承树图。你一定见过不少C++、Java、C#类库的继承树图。在Go中,类的继承树并无意义,你只需要知道这个类实现了哪些方法,每个方法是啥含义就足够了。其二,实现类的时候,只需要关心自己应该提供哪些方法,不用再纠结接口需要拆得多细才合理。接口由使用方按需定义,而不用事前规划。其三,不用为了实现一个接口而导入一个包,因为多引用一个外部的包,就意味着更多的耦合。接口由使用方按自身需求来定义,使用方无需关心是否有其他模块定义过类似的接口
- 将对象实例赋值给接口;
- 将接口实例赋值给接口;
//对象赋值给接口var interfaces IStudent=NewStudent("Jessica","male",18,"class1","grade1")interfaces.Go2School()
package one
type ReadWriterinterface{
Read(buf []byte)(n int, err error)
Write(buf []byte)(n int, err error)
}
package two
type IStreaminterface{
Write(buf []byte)(n int, err error)
Read(buf []byte)(n int, err error)
}
任何实现了one.ReadWriter接口的类,均实现了two.IStream; 任何one.ReadWriter接口对象可赋值给two.IStream,反之亦然; 在任何地方使用one.ReadWriter接口与使用two.IStream并无差异。
var file1 two.IStream=new(File)
var file2 one.ReadWriter= file1
var file3 two.IStream= file2
type Writer interface {Write(buf []byte) (n int, err error)}
var file1 two.IStream = new(File)var file4 Writer = file1
// OOPTest project main.go
package main
type IStudentinterface{
Go2School()
}
type IPersoninterface{
Speak(word string)
Eat(food string)
}
func main(){
//std := NewStudent("Jessica", "male", 18, "class1", "grade1")
//psn := NewPerson("James", "female", 20)
//语句switch中的value必须是接口类型,变量str的类型为转换后的类型。/
varIStdinterface{}=NewStudent("Jessica","male",18,"class1","grade1")
switch per :=IStd.(type){
caseIStudent:
per.Go2School()
caseIPerson:
per.Eat("pig")
}
}类型断言
// OOPTest project main.go
package main
type IStudentinterface{
Go2School()
}
type IPersoninterface{
Speak(word string)
Eat(food string)
}
func main(){
//std := NewStudent("Jessica", "male", 18, "class1", "grade1")
//psn := NewPerson("James", "female", 20)
//语句switch中的value必须是接口类型,变量str的类型为转换后的类型。
varIStdinterface{}=NewStudent("Jessica","male",18,"class1","grade1")
//switch per := IStd.(type) {
//case IStudent:
// per.Go2School()
//case IPerson:
// per.Eat("pig")
//}
//上面的转换有一个问题,如果该值不包含一个字符串,则程序会产生一个运行时错误。为了避免这个问题,可以使用"comma, ok"的习惯用法来安全地测试值是否为一个字符串:
if types, ok :=IStd.(IStudent); ok {
types.Go2School()
}elseif types, ok :=IStd.(IPerson); ok {
types.Eat("pig")
}
}
接口组合:接口的继承
type IStudentinterface{Go2School()}type IPersoninterface{Speak(word string)Eat(food string)}type Animalinterface{IPersonIStudent}
var v1 interface{}=1// 将int类型赋值给interface{}var v2 interface{}="abc"// 将string类型赋值给interface{}var v3 interface{}=&v2 // 将*interface{}类型赋值给interface{}var v4 interface{}=struct{ X int}{1}var v5 interface{}=&struct{ X int}{1}
func Printf(fmt string, args ...interface{})func Println(args ...interface{})