(1)面向对象

2018-01-05  本文已影响0人  爱喝咖啡的土拨鼠

类型系统

类型系统是指一个语言的类型体系结构。一个典型的类型系统通常包含以下内容:

类型系统描述的是这些内容在一个语言中如何被关联。

以java举例,在Java中存在两套完全独立的类型系统:一套是值类型系统,主要是基本数据类型(int byte char 等 ),这些类型是值语义的。另一套则是以Object为根的对象类型,这些类型可以定义成员变量和成员方法。java中的Any类型就是Object,值类型想要被Object引用需要装箱(int->Integer)。

相比之下Go语言的大多数类型都是值语义,并且都可以包含对应的操作方法。在需要的时候可以给任何类型添加新方法。而在实现某个接口时,无需从该接口继续(Go不支持继承),只要实现该接口要求的所有方法即可。GO语言的Any类型就是空接口interface(),可以引用任何类型。

为类型添加方法

例1:

package main

import "fmt"

type Integer int

func (a Integer) Less(b Integer) bool  {
    return a<b
}

func main()  {
    var a Integer =1
    if a.Less(2){
        fmt.Println(a,"less 2")
    }
}


运行结果:
1 less 2

Process finished with exit code 0

例1 定义了一个新类型Integer,我们为其新增了一个Less方法。

例2:

package main
import "fmt"
type Integer int

func (a *Integer) Add(b Integer) {
    *a += b
}

func main()  {
    var a Integer =1
    a.Add(2)
    fmt.Println(a)
}

Go语言中的面向对象最为直观,如果要求对象必须以指针传递,这有时会是个额外成本,有时对象很小,用指针传递并不划算。
只有在你需要修改对象的时候,才必须使用指针,比如例2
如果你写成这样

func (a *nteger) Add(b Integer) {
    a += b
}

那么你得打的值仍然会是1,而不是3。因为go语言类型都是属于值传递,要想修改变量的值,只能传递指针。

值语义和引用语义

值语义和引用语义的差别在于赋值
b = a
b.Modify()
如果b的修改不会影响a,属于值类型,如果影响属于引用类型。

Go语言中大多数属于值类型,包括:

Go语言中有4个类型比较特别,看起来像引用类型

结构体

Go 语言的结构体(struct)和其他语言的类(class)有同等地位,但Go放弃了包括继承在内的大量的面向对象的特性,只保留了组合这个最基础的特性。

定义一个矩形类型,再定义Area成员方法来计算面积

type Rect struct {
    x, y float64
    width, hight float64
}

func (rect *Rect)Area() float64 {
    return rect.hight*rect.width
}
初始化

定义好了Rect,可以有以下几种方式初始化:

rect1 := new(Rect)
rect2 :=&Rect{0,0,100,100}
rect3 :=&Rect{width:100,hight:100}
rect4 :=&Rect{}

Go语言没有构函数,使用一个全局的创建函数new来创建

匿名组合

确切的说,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()
}

以上代码定义了一个Base类,实现了Foo()和Bar(),然后定义了一个Foo类,该类从Base类“继承”并改写了Bar()

可见性

Go语言对关键字的增加非常的吝啬,其中没有private、protected、public这样的关键字,要使某个符号对其他包可见,需要定义此符号定义为大写字母

接口

接口在Go语言有着至高重要的地位,接口是Go语言整个类型系统的基石,让Go语言在基础编程哲学的探索上达到前所未有的高度。

非侵入式接口

在Go语言中,一个类只需要实现了接口所有的函数,我们就说这个类实现了该接口,甚至可以不知道接口的存在,例如以下File类并没有继承IFile IRead IWrite,但是实现了这些接口,所以就可以进行赋值。

type IFile interface{
  Read (buf []byte) (n int,err error)
  Write(buf []byte)(n int,err error)
  Seek(off int64,whene int)(pos int64,err error)
  Close(err error)
}

type IRead interface{
 Read (buf []byte) (n int,err error)
}

type IWrite interface{
    Write (buf []byte) (n int,err error)
}

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,whene int)(pos int64,err error){}
func (f *File) Close(err error){}

//赋值
var file1 IFile = new(File)
var file2 IRead = new(File)
var file3 IWrite = new(File)
接口赋值

接口赋值在Go语言中有两种情况:
将对象实例赋值给接口
将一个接口赋值给另一个接口

将某种类型的对象赋值给接口

type Integer int
func (a Integer) Less (b Integer)bool{
    return a<b
}

func (a *Integer) Add (b Integer)bool{
    *a +=b
}

//定义接口LessAdder
type LessAdder interface{
    Less (b Integer)bool
    Add (b Integer)
}

//将对象赋值给接口
var a Integer = 1
var b LessAdder =&a  (1)
var b LessAdder =a   (2)

//其中(1)是正确的赋值是(1)
上一篇 下一篇

猜你喜欢

热点阅读