面向对象编程

声明:内容来自《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}
GO语言快速入门 文章被收录于专栏

帮助GO初学者快速入门Golang

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务