go中的面向对象

81 阅读4分钟

因为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语言实战》