Golang方法
Go语言借助方法来实现OOP
Go语言OOP的两个关键是封装和组合
一、方法
- 方法是属于某种类型的,方法可以被声明到任意类型,只要不是一个指针或者一个interface。
值类型和引用类型:
(1)值类型包括:基本数据类型int系列、float系列、bool、string、数组和结构体;
(2)引用类型:指针、slice切片、map、管道channel、interface等;
值类型和引用类型的区别: (1)值类型,变量直接存储,内存通常在栈中分配;
(2)引用类型:变量存储的是一个地址,这个地址对应的空间才是真正存储的数据值,内存通常在堆上分配,当没有任何变量引用这个地址时,此地址对应的数据空间就是一个垃圾,由GC来回收;
type Point struct {
x, y float64
}
//function
func Distance(p, q Point) float64 {
return math.Hypot(q.x-p.x, q.x-p.x)
}
//method
//p为方法的接收器(receiver),接收器的名字建议用类型的第一个字母或第2个word的第一个字母
func (p Point) Distance(q Point) float64 {
return math.Hypot(q.x-p.x, q.y-p.y)
}
p := Point{1, 2}
q := Point{4, 6}
fmt.Println(Distance(p, q)) // "5", function call
fmt.Println(p.Distance(q)) // "5", method call
//p.Distance被称为选择器
//计算线段的长度
// A Path is a journey connecting the points with straight lines.
type Path []Point
// Distance returns the distance traveled along the path.
func (path Path) Distance() float64 {
sum := 0.0
for i := range path {
if i > 0 {
sum += path[i-1].Distance(path[i])
}
}
return sum
}
- 基于指针对象的方法
接收器的对象本身占用内存很大时,最好用指针声明方法 如果对象的某个方法的接收器为指针,那么该对象的所有方法都要使用指针做接收器
func (p *Point) ScaleBy(factor float64) {
p.X *= factor
p.Y *= factor
}
//调用方法
1.
r := &Point{1, 2}
r.ScaleBy(2)
fmt.Println(*r) // "{2, 4}"
2.
p := Point{1, 2}
pptr := &p
pptr.ScaleBy(2)
fmt.Println(p) // "{2, 4}"
3.
p := Point{1, 2}
(&p).ScaleBy(2)
fmt.Println(p) // "{2, 4}"
//上述2和3可以使用对象直接调用方法,Go会自动用对应的指针去调用方法
p := Point{1, 2}
p.ScaleBy(2)
- nil 也是合法的接收器类型
// An IntList is a linked list of integers.
// A nil *IntList represents the empty list.
type IntList struct {
Value int
Tail *IntList
}
// Sum returns the sum of the list elements.
func (list *IntList) Sum() int {
if list == nil {
return 0
}
return list.Value + list.Tail.Sum()
}
- 方法值和方法表达式
,选择器会返回一个方法"值"-> 一个将方法(Point.Distance)绑定到特定接收器变量的函数
p := Point{1, 2}
q := Point{4, 6}
distanceFromP := p.Distance // method value
fmt.Println(distanceFromP(q)) // "5"
var origin Point // {0, 0}
fmt.Println(distanceFromP(origin)) // "2.23606797749979", sqrt(5)
scaleP := p.ScaleBy // method value
scaleP(2) // p becomes (2, 4)
scaleP(3) // then (6, 12)
scaleP(10) // then (60, 120)
二、封装
- 定义
一个对象的变量或者方法如果对调用方是不可见的话,一般就被定义为“封装”。封装有时候也 被叫做信息隐藏。
- 优点
(1) 调用方不能直接修改对象的变量值
(2) 隐藏实现的细节
(3) 阻止了外部调用方对对象内部的值任意地进行修改
- 封装并不总是理想的。
三、总结
方法只是OOP编程里的半边天,另一半是接口。