声明:内容来自《Go语言编程》
[TOC]
Go语言对面向对象编程的支持是语言类型系统中的天然组成部分
1 类型系统
类型系统是指一个语言的类型体系结构
1.1 为类型添加方法
type Integer int
func (a Integer) Less(b Integer) bool {
return a < b
} 关于给类型添加方法的时候,类型的参数是传入指针?还是值传递?如下:
func (a *Integer) Add(b Integer) {
*a += b
}
func (a Integer) Add(b Integer) {
a += b
}
这取决于,你是否需要需要修改对象!若需要修改对象,则需要传入指针。类型都是基于值传递的。要想修改变量的值,只能 传递指针
1.2 结构体
type Rect struct {
x, y float64
width, height float64
}
func (r *Rect) Area() float64 {
return r.width * r.height
} 2 初始化
rect1 := new(Rect)
rect2 := &Rect{}
rect3 := &Rect{0, 0, 100, 200}
rect4 := &Rect{width: 100, height: 200} - 未进行显式初始化的变量都会被初始化为该类型的零值。例如bool类型的零 值为false,int类型的零值为0,string类型的零值为空字符串。
- 在Go语言中没有构造函数的概念,对象的创建通常交由一个全局的创建函数来完成,以 NewXXX来命名,表示“构造函数”:
func NewRect(x, y, width, height float64) *Rect {
return &Rect{x, y, width, height}
} 3 匿名组合
Go语言也提供了继承,但是采用了组合的文法,所以我们将其称为匿名组合。
type Base struct {
Name string
}
func (base *Base) Foo() { ... }
func (base *Base) Bar() { ... }
type Foo struct {
Base
...
}
func (foo *Foo) Bar() {
foo.Base.Bar()
...
} 4 接口
Go语言在编程哲学上是变革派,是因为Go语言的类型系统,更是因为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) 尽管File类并没有从这些接口继承,甚至可以不知道这些接口的存在,但是File类实现了 这些接口,可以进行赋值。
非侵入式接口的好处:
- Go语言的标准库,再也不需要绘制类库的继承树图。
- 实现类的时候,只需要关心自己应该提供哪些方法,不用再纠结接口需要拆得多细才合理。
- 不用为了实现一个接口而导入一个包,因为多引用一个外部的包,就意味着更多的耦合。
在Go语言中,只要两个接口拥 有相同的方法列表(次序不同不要紧),那么它们就是等同的,可以相互赋值。
4.1 接口查询
var file1 Writer = ...
if file5, ok := file1.(two.IStream); ok {
...
} 这个if语句检查file1接口指向的对象实例是否实现了two.IStream接口,如果实现了,则执 行特定的代码。
4.2 类型查询
var v1 interface{} = ...
switch v := v1.(type) {
case int: // 现在v的类型是int
case string: // 现在v的类型是string
...
} 5 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} 
京公网安备 11010502036488号