Golang之面向对象

简介: 一、method         带有接收者的函数,称之为method。         假设定义了一个struct叫长方形,现在要计算它的面积,那么按照面向过程的思路会如下实现:         packeage main         import "fmt"    ...
一、method
        带有接收者的函数,称之为method。
        假设定义了一个struct叫长方形,现在要计算它的面积,那么按照面向过程的思路会如下实现:
        packeage main
        import "fmt"
        type Rectange struct {
            width, height float64
        }
        func area(r Rectangle) float64 {
            return r.width*r.height
        }
        func main() {
            r1 := Rectangle(12, 2)
            r2 := Rectangle(9, 4)
            fmt.Println("Area of r1 is: ", area(r1))
            fmt.Println("Area of r2 is: ", area(r2))
        }
        这段代码中,area不是Rectangle的方法,所以需要将r1,r2作为参数传入以计算面积。我们知道C语言是不能重载的,为了解决新增类型比如圆、五边形等问题则需要为此定义多个不同名的面积计算函数,比如:area_circle、area_triangle。这种方式相对于C++的重载来看不是很优雅,在Go语言中,用了类似的解决方案,即method。
        method附属在一个给定的类型上,它的语法和函数的声明语法几乎一样,只是在func后面增减了一个receiver(也就是method所依从的主体),简单点说就是struct拥有方法area。method的语法如下:
        func (r ReceiverType) funcName(parameters) (results)
        将前面例子改造如下:
        package main
        import (
            "fmt"
            "math"
        )
        type Rectangle struct {
            width, height float64
        }
        type Circle struct {
            radius float64
        }
        func (r Rectangle) area() float64 {
            return r.width*r.height
        }
        func (c Circle) area() float64 {
            return c.radius*c.radius*math.pi
        }
        func main() {
            r1 := Rectangle(12, 2)
            r2 := Rectangle(9, 4)
            c1 := Circle(10)
            c2 := Circle(25)

            fmt.Println("Area of r1 is: ", r1.area())
            fmt.Println("Area of r2 is: ", r2.area())
            fmt.Println("Area of c1 is: ", c1.area())
            fmt.Println("Area of c2 is: ", c2.area())
        }
        使用method的时候需要注意以下几点:
        (1)虽然method的名字一模一样,但是如果接收者不一样,那么method就不一样。
        (2)method里面可以访问接收者的字段。
        (3)调用method通过访问,就像struct里面访问字段一样。
        在上面的例子中,method方法中的Receiver是以值传递,而非引用传递。实际上,Receiver还可以是指针,二者区别在于:指针作为Receiver会对实例对象的内容发生操作,而普通类型作为Receiver仅仅是以副本作为操作对象,并不对原实例对象发生操作。
        method其实不仅仅可以用在struct上,而且可以用在任何自定义的类型、内置类型、struct等上面。当然struct也是自定义类型中的一个特例,你还可以通过如下形式来申明自定义类型:
        type typeName typeLiteral
        具体例子如下:
        type ages int
        type money float32
        type months map[string]int
        实际上自定义类型只是为内置类型定义了一个别名而已,类似于C语言中的typedef,如上面所示用ages替代了int。
        
二、method继承
        method也可以继承,如果匿名字段实现了一个method,那么包含这个匿名字段的struct也能调用该method,举例如下:
        package main
        import "fmt"
        type Human struct {
            name string
            age int
            phone string
        }
        type Student struct {
            Human    //匿名字段
            school 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)
        }
        func main() {
            mark := Student{Human{"Mark", 25, "222-222-YYY"}, "MIT"}
            sam := Employee{Human{"Sam", 45, "111-888-XXX"}, "Golang Inc"}
            mark.SayHi()
            sam.SayHi()
        }

三、method重写
        method还能重写,类似于匿名字段冲突的处理方式。
        我们可以在Emplyee上面定义一个method,重写匿名字段的方法,具体如下:
        package main
        import "fmt"
        type Human struct {
            name string
            age int
            phone string
        }
        type Student struct {
            Human    //匿名字段
            school 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)
        }
        func main() {
            mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"}
            sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}
            mark.SayHi()
            sam.SayHi()
        }
        看了上面的代码是否看到了C++的影子啊,呵呵。
        通过这些内容,我们可以设计出基本的面向对象的程序,但是Go语言的面向对象非常简单,没有任何的私有、公有关键字,通过大小写来实现(大写开头的为公有,小写开头的为私有),方法也也同样适用这个原则。






        


目录
相关文章
|
11月前
|
Go 数据库
Golang面向对象小案例(未连接数据库)
Golang面向对象小案例(未连接数据库)
34 0
|
12月前
|
Cloud Native Java 编译器
100天精通Golang(基础入门篇)——第21天:Go语言面向对象(OOP)核心概念解析
100天精通Golang(基础入门篇)——第21天:Go语言面向对象(OOP)核心概念解析
115 0
|
存储 Kubernetes 算法
【Golang 快速入门】基础语法 + 面向对象
Golang 语言特性 Golang 的优势 Golang 的应用场景 Golang 的不足 基础语法 main 变量 常量与 iota string 字符串遍历 strings 包 bytes 包 strconv 包 unicode 包 循环语句 range 函数 多返回值 init 函数 闭包 import 导包 匿名函数 指针 defer 切片 slice 数组 slice slice 操作 ... map map 的声明 map 的使用 error 面向对象编程 type 方法 struct 封装
185 0
|
1月前
|
Go
Golang语言之管道channel快速入门篇
这篇文章是关于Go语言中管道(channel)的快速入门教程,涵盖了管道的基本使用、有缓冲和无缓冲管道的区别、管道的关闭、遍历、协程和管道的协同工作、单向通道的使用以及select多路复用的详细案例和解释。
53 4
Golang语言之管道channel快速入门篇
|
1月前
|
Go
Golang语言文件操作快速入门篇
这篇文章是关于Go语言文件操作快速入门的教程,涵盖了文件的读取、写入、复制操作以及使用标准库中的ioutil、bufio、os等包进行文件操作的详细案例。
46 4
Golang语言文件操作快速入门篇
|
1月前
|
Go
Golang语言之gRPC程序设计示例
这篇文章是关于Golang语言使用gRPC进行程序设计的详细教程,涵盖了RPC协议的介绍、gRPC环境的搭建、Protocol Buffers的使用、gRPC服务的编写和通信示例。
52 3
Golang语言之gRPC程序设计示例
|
1月前
|
安全 Go
Golang语言goroutine协程并发安全及锁机制
这篇文章是关于Go语言中多协程操作同一数据问题、互斥锁Mutex和读写互斥锁RWMutex的详细介绍及使用案例,涵盖了如何使用这些同步原语来解决并发访问共享资源时的数据安全问题。
43 4
|
1月前
|
Go
Golang语言错误处理机制
这篇文章是关于Golang语言错误处理机制的教程,介绍了使用defer结合recover捕获错误、基于errors.New自定义错误以及使用panic抛出自定义错误的方法。
39 3
|
1月前
|
Go 调度
Golang语言goroutine协程篇
这篇文章是关于Go语言goroutine协程的详细教程,涵盖了并发编程的常见术语、goroutine的创建和调度、使用sync.WaitGroup控制协程退出以及如何通过GOMAXPROCS设置程序并发时占用的CPU逻辑核心数。
27 4
Golang语言goroutine协程篇
下一篇
无影云桌面