传统的面向对象编程

intint

对象可以使用属于它的普通变量来存储数据。这种从属于对象或类的变量叫作字段(Field)。对象还可以使用属于类的函数来实现某些功能,这种函数叫作类的方法(Method)。这两个术语很重要,它有助于我们区分函数与变量,哪些是独立的,哪些又是属于类或对象的。总之,字段与方法通称类的属性(Attribute)

方法

在 Golang 中,方法是作用在接收者(receiver)上的一个函数,接收者是某种类型的变量;接收者可以是任意类型(指针、接口除外),包括结构体类型、函数类型、可以是 int ,boll,string或数组别名类型。

  • 接收者不能是一个接口类型,因为接口是一个抽象定义,方法却必须要具体实现
  • 接收者不能是一个指针类型,但可以是任何其他类型允许的指针

方法重载

Add*denseMatrix*sparseMatrix
//a是接收器变量,*denseMatrix和*sparseMatrix是接收器类型,Add是方法,b Matrix是参数列表,Matrix是返回参数
func (a *denseMatrix) Add(b Matrix) Matrix
func (a *sparseMatrix) Add(b Matrix) Matrix

接收器的标准格式

recvreceiver_typemethodNameparamater_listreturn_value_list
func (recv receiver_type)methodName(paramater_list)(return_value_list) {...}

接收器的类型

在计算机中,小对象由于值复制时的速度较快,所以适合使用非指针接收器,大对象因为复制性能较低,适合使用指针接收器,在接收器和参数间传递时不进行复制,只是传递指针。

//定义TwoInts结构体
type TwoInts struct {
    a int
    b int
}
func main(){
    two1 := new(TwoInts)//实例化,返回指针*TwoInts
    two1.a = 12
    two1.b = 10
    //调用AddThem方法
    fmt.Println(two1.AddThem())
    //调用AddToParam方法
    fmt.Println(two1.AddToParam(20))

    two2 := TwoInts{3,4} //实例化,返回结构体TwoInts{3,4}
    //调用AddThem方法
    fmt.Println(two2.AddThem())
}
//指针接收器的两个值相加方法
func (tn *TwoInts)AddThem()int{
    return tn.a + tn.b
}
//指针接收器的三个值相加方法
func (tn *TwoInts)AddToParam(param int)int{
    return tn.a + tn.b + param
}

/*
22
42
7
*/
// 定义点结构
type Point struct {
    X int
    Y int
}
// 非指针接收器的加方法
func (p Point) Add(other Point) Point {
    // 成员值与参数相加后返回新的结构
    return Point{p.X + other.X, p.Y + other.Y}
}
func main() {
    // 初始化点
    p1 := Point{3, 4}
    p2 := Point{2, 5}
    // 与另外一个点相加
    result := p1.Add(p2)
    // 输出结果
    fmt.Println(result.X,result.Y,result)
}

/*
5 9 {5 9}
*/

### 函数和方法的区别

函数将变量作为参数:Function(recv);方法在变量上被调用:recv.Method1()

  • 当接收者是指针时,方法可以改变接收者的值和状态。(对于方法来说)
  • 当参数作为指针传递时,即通过引用调用时,函数也可以改变参数的状态。(对于函数来说)

### Golang设计模式之工厂方法

newNew
//不强制构造函数,首字母大写
type File struct {
    fd int
    name string
}

//构造工厂方法
func NewFile(fd int,name string) *File{
    if fd < 0 {
        return nil
    }
    return &File{fd,name}
}

func main() {
    //调用工厂方法NewFile
    f := NewFile(10,"./test.yxy")
    fmt.Println(f)
    //计算结构体占用多少内存
    size := unsafe.Sizeof(File{})
    fmt.Println(size)
}

/*
&{10 ./test.yxy}
24
*/

代码说明:

FileNewFile*Filemain
new

### 指针或值作为接收者

如果想要方法改变接收者的数据,就在接收者的指针类型上定义该方法。否则,就在普通的值类型上定义方法。

change()Bwrite()BB
  type B struct {
      thing int
  }
  
  func (b *B) change() {
      b.thing = 1
  }
  
  func (b B) write() string { 
      return fmt.Sprint(b) 
  }
  
  func main() {
      var b1 B // b1是值
      b1.change()
      fmt.Println(b1.write())
  
      b2 := new(B) // b2是指针
      b2.change()
      fmt.Println(b2.write())
  }
  
  /* 
  {1}
  {1}
  */