go语言-面向对象编程

值类型和引用类型

go语言中的类型绝大部分都是值类型,有四种类型可以看做是引用类型:
 数组切片:指向数组(array)的一个区间。
 map:极其常见的数据结构,提供键值查询能力。
 channel:执行体(goroutine)间的通信设施。
 接口(interface):对一组满足某个契约的类型的抽象。

结构体

Go语言放弃了包括继承在内的大量面向对象特性,只保留了组合(composition)这个最基础的特性。

初始化结构体
type Rect struct {
    x, y float64
    width, height float64
}
//四种初始化结构体的方法.未进行显式初始化的变量都会被初始化为该类型的零值,例如bool类型的零
值为falseint类型的零值为0string类型的零值为空字符串。
rect1 := new(Rect)
rect2 := &Rect{}
rect3 := &Rect{0, 0, 100, 200}
rect4 := &Rect{width: 100, height: 200}
//Go语言中没有构造函数的概念,对象的创建通常交由一个全局的创建函数来完成,以NewXXX来命名,表示“构造函数”:
func NewRect(x, y, width, height float64) *Rect {
    return &Rect{x, y, width, height}
}

匿名组合

Go语言采用了组合的文法实现继承,我们将其称为匿名组合:

//定义了一个Base类,然后定义了一个Foo类,该类从Base类“继承”并改写了Bar()方法
type Base struct {
    Name string
}
func (base *Base) Foo() { ... }
func (base *Base) Bar() { ... }
type Foo struct {
    Base
    ...
}
func (foo *Foo) Bar() {
    foo.Base.Bar()
    ...
}

以上代码中 ,结构体Foo继承了Base(组合了Base),Foo的实例可以直接使用Bar()方法,也可以用Base.Bar()来调用Base的Bar()方法。Foo的实例可以直接用Foo.Foo()来调用Base的Foo方法。此处的继承和java中的继承除了实现方法不同外,效果是一致的。继承(组合)了父类之后,可以调用父类的方法,重写父类的方法,重写之后还可以调用父类的方法。如果子类和父类中有相同的属性名,父类的属性名会被屏蔽。

可见性

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

//这里我们定义了一个File类,并实现有Read()、Write()、Seek()、Close()等方法。设想我们有如下接口:
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)
接口赋值

只要两个接口拥有相同的方法列表(次序不同不要紧),那么它们就是等同的,可以相互赋值。
接口赋值并不要求两个接口必须等价。如果接口A的方法列表是接口B的方法列表的子集,
那么接口B可以赋值给接口A,反之则不成立。如果要讲接口A赋值给接口B,则需要接口查询:

var file1 Writer = ...
if file5, ok := file1.(two.IStream); ok {
    ...
}

以上代码就是接口查询,查询file1是否也有two.IStream接口中的方法,如果有,则可以赋值。

接口组合
// ReadWriter接口将基本的ReadWrite方法组合起来
type ReadWriter interface {
    Reader
    Writer
}
//这个接口组合了ReaderWriter两个接口,它完全等同于如下写法:
type ReadWriter interface {
    Read(p []byte) (n int, err error)
    Write(p []byte) (n int, err error)
}

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}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值