golang知识整理(1)---面向对象
本文用于整理golang和面向对象有关的技术,忽略了一些与其他语言相似的特性,着重关注golang自身特性,主要包括下面几个方面:
- struct匿名字段
- method及其特性
- interface及其特性
struct匿名字段
匿名字段是指struct中只提供类型,不提供变量名的字段,也称为嵌入字段。
当匿名字段是一个struct的时候,那么这个struct所拥有的全部字段都被隐式地引入了当前定义的这个struct。
type Human struct {
name string
age int
weight int
}
type Student struct {
Human // 匿名字段,那么默认Student就包含了Human的所有字段
speciality string
}
当匿名字段内部和外部出现同名字段时,优先访问外层的字段。
例如:
type Human struct {
name string
age int
phone string // Human类型拥有的字段
}
type Employee struct {
Human // 匿名字段Human
speciality string
phone string // 雇员的phone字段
}
当需要调用Employee对象中Human的phone字段时,可以用如下方式访问:
Bob := Employee{Human{"Bob", 34, "777-444-XXXX"}, "Designer", "333-222"}
fmt.Println("Bob's work phone is:", Bob.phone)
// 如果我们要访问Human的phone字段
fmt.Println("Bob's personal phone is:", Bob.Human.phone)
method及其特性
golang的方法叫作method,它没有类内部的方法,method的语法如下:
func (r ReceiverType) funcName(parameters) (results)
receiver表示调用该方法的对象类型,可以通过设置不同的receiver类型来实现多态。
method可以设置指针作为receiver的类型,这样才可以改变receiver内部数据的值,如下所示:
func (b *Box) SetColor(c Color) {
b.color = c
}
另外当receiver为指针时,go可以通过指针直接访问实体的字段,而不需要转成实体,因此函数中*b.Color=c和b.Color=c都是可以的。
如果匿名字段实现了某个method,继承这个匿名字段的类也可以调用这个method,例如:
type Human struct {
name string
age int
phone string
}
type Student struct {
Human //匿名字段
school string
}
//在human上面定义了一个method
func (h *Human) SayHi() {
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
}
func main() {
mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"}
mark.SayHi()
}
继承了匿名字段method的方法也可以重写自己的同名method,如下所示:
type Human struct {
name string
age int
phone string
}
type Employee struct {
Human //匿名字段
company string
}
//Human定义method
func (h *Human) SayHi() {
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
}
//Employee的method重写Human的method
func (e *Employee) SayHi() {
fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,
e.company, e.phone) //Yes you can split into 2 lines here.
}
func main() {
sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}
sam.SayHi()
}
interface及其特性
interface是一组method的组合,我们通过interface来定义对象的一组行为。实现了interface中所有method的struct就可以说实现了这个interface。如下所示:
type Human struct {
name string
age int
phone string
}
//Human对象实现Sayhi方法
func (h *Human) SayHi() {
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
}
// Human对象实现Sing方法
func (h *Human) Sing(lyrics string) {
fmt.Println("La la, la la la, la la la la la...", lyrics)
}
//Human对象实现Guzzle方法
func (h *Human) Guzzle(beerStein string) {
fmt.Println("Guzzle Guzzle Guzzle...", beerStein)
}
// 定义interface
type Men interface {
SayHi()
Sing(lyrics string)
Guzzle(beerStein string)
}
Human实现了Men中所有的接口,那么就可以说Human实现了Men。同时被实现的interface也可以存实现这个interface的所有对象,如下所示:
type Men interface {
SayHi()
Sing(lyrics string)
}
func main() {
mike := Student{Human{"Mike", 25, "222-222-XXX"}, "MIT", 0.00}
paul := Student{Human{"Paul", 26, "111-222-XXX"}, "Harvard", 100}
sam := Employee{Human{"Sam", 36, "444-222-XXX"}, "Golang Inc.", 1000}
tom := Employee{Human{"Tom", 37, "222-444-XXX"}, "Things Ltd.", 5000}
//定义Men类型的变量i
var i Men
//i能存储Student
i = mike
fmt.Println("This is Mike, a Student:")
i.SayHi()
i.Sing("November rain")
//i也能存储Employee
i = tom
fmt.Println("This is tom, an Employee:")
i.SayHi()
i.Sing("Born to be wild")
//定义了slice Men
fmt.Println("Let's use a slice of Men and see what happens")
x := make([]Men, 3)
//这三个都是不同类型的元素,但是他们实现了interface同一个接口
x[0], x[1], x[2] = paul, sam, mike
for _, value := range x{
value.SayHi()
}
}
Men、Student、Employee三个类均实现了Men接口,因此均可以用Men类型的对象来存储。
另外,空的interface可以存储任意类,这点有点类似c++中的void*类。
根据interface的上述特性,还可以将实现了interface的对象作为参数输入以interface为参数的函数中,以实现函数的变类型参数输入。例如fmt.Println实现变参数输入就是用如下的Stringer接口来实现的,任何实现了这个Stringer接口的对象都可以作为参数被fmt.Println调用。
type Stringer interface {
String() string
}
Go语言还可以通过断言语法来判断interface所存变量的类型,如下所示:
value, ok := element.(int)
类似于struct的匿名字段,interface也有一种匿名interface可以将一个interface继承至另一个interface,获得其中所有的接口,如下所示:
type Interface interface {
sort.Interface //嵌入字段sort.Interface
Push(x interface{}) //a Push method to push elements into the heap
Pop() interface{} //a Pop elements that pops elements from the heap
}