因为go和以往学的java区别有不少,在类和继承等问题上有些没弄明白,就简单整理总结一下
struct类型
对属性封装,类似于类(class)的简化形式,通过首字母大小写确定共有私有,但是,相对于class,只能声明“类成员”,不能声明“类方法”
// 声明struct类型的方法
type Human struct {
name string
age int
weight int
}
// struct的匿名字段,自定义类型和内置类型均可作为匿名字段,以此方式进行继承
type student struct {
Human // 匿名字段,那么默认Student包含了Human的所有字段
speciality string
}
function
使用func关键字声明 ,关键字后紧跟函数名、参数列表和返回值。允许有多个返回值。
defer关键字:安排随后的函数调用在函数返回时才按defer出现的先后顺序倒序执行
func funcName(parameters) (results)
method
// method语法
func (r ReceiverType) funcName(parameters) (results)
相对于函数,method在关键字func和方法名之间添加了一个参数(一个struct类型)
method类似于Java中的类的成员方法
method可以定义在任何自定义的类型、内置类型、struct等类型上
method继承:假设上文中Human有自己的method,那么Student也可以使用它的method,Student可重写该方法
interface
go中的interface和其他语言的interface不同
interface是一组抽象method的组合,必须由其它非interface类型来实现,interface用来定义对象的一组行为,是对其他行为的抽象概括,可以通过接口实现多态
如果某个对象实现了某个接口的所有方法,则此对象就实现了此接口,所有使用这个接口的地方都支持这种类型的值
go语言通过interface来实现duck-typing:”当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来像鸭子,那么这只鸟就可以被成为鸭子“
interface可存储实现了这个interface的任意类型对象
package main
import "fmt"
type Human struct {
name string
age int
phone string
}
type Student struct {
Human // 匿名字段,继承Human
school string
loan float32
}
type Employee struct {
Human // 匿名字段
company string
money float32
}
// Human 定义method
func (h *Human) SayHi() {
fmt.Printf("Hi, I am %v you can call me on %v\n", h.name, h.phone)
}
// Human 对象实现Sing方法
func (h *Human) Sing(lyrics string) {
fmt.Println("Happy New Year~", lyrics)
}
// Human 对象实现Guzzle方法
func (h *Human) Guzzle(beerStein string) {
fmt.Println("Guzzle Guzzle Guzzle...", beerStein)
}
// Employee重载Human的SayHi方法
func (e *Employee) SayHi() {
fmt.Printf("Hi, I am %v, I work at %s, call me on %s\n", e.name, e.company, e.phone)
}
// Student 实现BorrowMoney方法
func (s *Student) BorrowMoney(amount float32) {
s.loan += amount // again and again and...
}
// Empolyee 实现SpendSalary方法
func (e *Employee) SpendSalary(amount float32) {
e.money -= amount
}
// 定义interface,interface可被任意的对象实现,如果定义了一个interface变量,变量内可存放实现这个interface的任意类型的对象
// 这里定义了一个Meninterface类型的变量m,m里可以存储Human、Student或Employee值,m可以持有这三种类型的对象
// 这个slice可以被赋予实现了Men接口的任意结构对象
type Men interface {
SayHi()
Sing(lyrics string)
Guzzle(beerStein string)
}
type YoungChap interface {
SayHi()
Sing(song string)
BorrowMoney(amount float32)
}
type ElderlyGent interface {
SayHi()
Sing(Song string)
SpendSalary(amount float32)
}
func main() {
sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc", 0}
tom := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Things Ltd.", 5000}
mike := Student{Human{"Mike", 25, "222-222-XXX"}, "MIT", 0.0}
paul := Student{Human{"Paul", 26, "111-222-xxx"}, "Harvard", 100}
mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT", 0}
mark.SayHi()
sam.SayHi()
// 定义Mental类型变量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)
// T这三个都是不同类型的元素,但是他们实现了interface同一个接口
x[0], x[1], x[2] = &paul, &sam, &mike
for _, value := range x {
value.SayHi()
}
//interface是一组抽象方法的集合,必须由其他非interface类型实现,不能自我实现
//Go语言通过interface实现了duck-typing,当一只鸟走起来像鸭子,游泳像鸭子,叫起来像鸭子,那么就是鸭子
}
空interface
interface{}不包含任何的method,所有的类型都实现了空interface,空interface在描述上不起作用,但可用来存储任意类型参数
var a interface{}
var i int = 5
s := "Hello world"
// a可以存储任意类型的值
a = i
a = s
interface函数参数可持有任意实现该接口类型的对象
package main
import (
"fmt"
"strconv"
)
type Human struct {
name string
age int
phone string
}
// 通过这个方法Human实现了fmt.Stringer,通过interface参数定义,接收各种类型的参数
func (h Human) String() string {
return " " + h.name + "-" + strconv.Itoa(h.age) + "years -" + h.phone + " "
}
func main() {
Bob := Human{"Bob", 39, "000-7777-XXX"}
fmt.Println("This Human is :", Bob)
}
相对而言,Go语言废弃了很多传统OOP的特性,也有很多不一样的使用方法,用Go做OOP需要多练练
参考:《Go web编程》《Go语言实战》