分享
go基本语法学习笔记之面向对象:接口
wolgame · · 2140 次点击 · · 开始浏览这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。
Go语言的接口并不是其他语言(C++、Java、C#等)中所提供的接口概念。
基于模块设计的单向依赖原则,模块A在实现自身的业务时,不应该关心某个具体使用方的要求。模版A实现的时候,甚至不知道会有如今B来使用它。
非侵入式接口
在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() errorFile类实现了4个方法如有接口:
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
}尽管File类并没有从这些接口继承,甚至可以不知道这些接口的存在,但是File类实现了这些接口,可以进行赋值:var file1 IFile = new(File) var file2 IReader = new(File) var file3 IWriter = new(File) var file4 ICloser = new(File)因为File类实现 接口 要求的 所有方法
接口赋值
接口赋值在Go语言中分为如下两种情况:- 将对象实例赋值给接口;
- 将一个接口赋值给另一个接口。
type Integer int
<pre name="code" class="plain">func (a Integer) Less(b Integer) bool {
return a < b
}func (a *Integer) Add(b Integer) { *a += b}
定义接口type LessAdder interface {
Less(b Integer) bool
Add(b Integer)
}var a Integer = 1 var b LessAdder = &a ... (1)ok <span style="font-family: Arial, Helvetica, sans-serif;"> </span>var b LessAdder = a ... (2)no
</pre><pre name="code" class="plain">GO可以根据
func (a Integer) Less(b Integer) bool
自动生成新方法
func (a *Integer) Less(b Integer) bool {
return (*a).Less(b)
}接口赋值并不要求两个接口必须等价。如果接口A的方法列表是接口B的方法列表的子集,那么接口B可以赋值给接口A。接口查询
var file1 Writer = ...
if file5, ok := file1.(two.IStream); ok {
...
}这个if语句检查file1接口指向的对象实例是否实现了two.IStream接口。 在Go语言中,你可以询问接口它指向的对象是否是某个类型,比如:
var file1 Writer = ...
if file6, ok := file1.(*File); ok { //这个if语句判断file1接口指向的对象实例是否是*File类型
...
}
类型查询
在Go语言中,还可以更加直截了当地询问接口指向的对象实例的类型,例如:var v1 interface{} = ...
switch v := v1.(type) {
case int: // 现在v的类型是int
case string: // 现在v的类型是string
...
}
接口组合
//接口中可以组合其它接口,这种方式等效于在接口中添加其它接口的方法
type Reader interface {
read()
}
type Writer interface {
write()
}
//定义上述两个接口的实现类
type MyReadWrite struct{}
func (mrw *MyReadWrite) read() {
fmt.Println("MyReadWrite...read")
}
func (mrw *MyReadWrite) write() {
fmt.Println("MyReadWrite...write")
}
//定义一个接口,组合了上述两个接口
type ReadWriter interface {
Reader
Writer
}
//上述接口等价于:
type ReadWriterV2 interface {
read()
write()
}
//ReadWriter和ReadWriterV2两个接口是等效的,因此可以相互赋值
func interfaceTest0104() {
mrw := &MyReadWrite{}
//mrw对象实现了read()方法和write()方法,因此可以赋值给ReadWriter和ReadWriterV2
var rw1 ReadWriter = mrw
rw1.read()
rw1.write()
fmt.Println("------")
var rw2 ReadWriterV2 = mrw
rw2.read()
rw2.write()
//同时,ReadWriter和ReadWriterV2两个接口对象可以相互赋值
rw1 = rw2
rw2 = rw1
}
Any类型
由于Go语言中任何对象实例都满足空接口interface{},所以interface{}看起来像是可以指向任何对象的Any类型,如下: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}有疑问加站长微信联系(非本文作者)
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
关注微信2140 次点击
上一篇:go语言学习笔记
添加一条新回复
(您需要 后才能回复 没有账号 ?)
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码` - 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传
收入到我管理的专栏 新建专栏
Go语言的接口并不是其他语言(C++、Java、C#等)中所提供的接口概念。
基于模块设计的单向依赖原则,模块A在实现自身的业务时,不应该关心某个具体使用方的要求。模版A实现的时候,甚至不知道会有如今B来使用它。
非侵入式接口
在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() errorFile类实现了4个方法如有接口:
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
}尽管File类并没有从这些接口继承,甚至可以不知道这些接口的存在,但是File类实现了这些接口,可以进行赋值:var file1 IFile = new(File) var file2 IReader = new(File) var file3 IWriter = new(File) var file4 ICloser = new(File)因为File类实现 接口 要求的 所有方法
接口赋值
接口赋值在Go语言中分为如下两种情况:- 将对象实例赋值给接口;
- 将一个接口赋值给另一个接口。
type Integer int
<pre name="code" class="plain">func (a Integer) Less(b Integer) bool {
return a < b
}func (a *Integer) Add(b Integer) { *a += b}
定义接口type LessAdder interface {
Less(b Integer) bool
Add(b Integer)
}var a Integer = 1 var b LessAdder = &a ... (1)ok <span style="font-family: Arial, Helvetica, sans-serif;"> </span>var b LessAdder = a ... (2)no
</pre><pre name="code" class="plain">GO可以根据
func (a Integer) Less(b Integer) bool
自动生成新方法
func (a *Integer) Less(b Integer) bool {
return (*a).Less(b)
}接口赋值并不要求两个接口必须等价。如果接口A的方法列表是接口B的方法列表的子集,那么接口B可以赋值给接口A。接口查询
var file1 Writer = ...
if file5, ok := file1.(two.IStream); ok {
...
}这个if语句检查file1接口指向的对象实例是否实现了two.IStream接口。 在Go语言中,你可以询问接口它指向的对象是否是某个类型,比如:
var file1 Writer = ...
if file6, ok := file1.(*File); ok { //这个if语句判断file1接口指向的对象实例是否是*File类型
...
}
类型查询
在Go语言中,还可以更加直截了当地询问接口指向的对象实例的类型,例如:var v1 interface{} = ...
switch v := v1.(type) {
case int: // 现在v的类型是int
case string: // 现在v的类型是string
...
}
接口组合
//接口中可以组合其它接口,这种方式等效于在接口中添加其它接口的方法
type Reader interface {
read()
}
type Writer interface {
write()
}
//定义上述两个接口的实现类
type MyReadWrite struct{}
func (mrw *MyReadWrite) read() {
fmt.Println("MyReadWrite...read")
}
func (mrw *MyReadWrite) write() {
fmt.Println("MyReadWrite...write")
}
//定义一个接口,组合了上述两个接口
type ReadWriter interface {
Reader
Writer
}
//上述接口等价于:
type ReadWriterV2 interface {
read()
write()
}
//ReadWriter和ReadWriterV2两个接口是等效的,因此可以相互赋值
func interfaceTest0104() {
mrw := &MyReadWrite{}
//mrw对象实现了read()方法和write()方法,因此可以赋值给ReadWriter和ReadWriterV2
var rw1 ReadWriter = mrw
rw1.read()
rw1.write()
fmt.Println("------")
var rw2 ReadWriterV2 = mrw
rw2.read()
rw2.write()
//同时,ReadWriter和ReadWriterV2两个接口对象可以相互赋值
rw1 = rw2
rw2 = rw1
}
Any类型
由于Go语言中任何对象实例都满足空接口interface{},所以interface{}看起来像是可以指向任何对象的Any类型,如下: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}