博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Golang之面向对象
阅读量:6119 次
发布时间:2019-06-21

本文共 3061 字,大约阅读时间需要 10 分钟。

一、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语言的面向对象非常简单,没有任何的私有、公有关键字,通过大小写来实现(大写开头的为公有,小写开头的为私有),方法也也同样适用这个原则。
        

转载地址:http://vzqka.baihongyu.com/

你可能感兴趣的文章
JSP EL表达式
查看>>
C#中调用Windows API时的数据类型对应关系[转]
查看>>
程序员/设计师能用上的 75 份速查表(转)
查看>>
.NET Core微服务之基于Polly+AspectCore实现熔断与降级机制
查看>>
.NET Core微服务系列基础文章索引(目录导航Draft版)
查看>>
淘淘商城第三天笔记
查看>>
lower_bound() 与 upper_bound()
查看>>
【.Net】在C#中判断某个类是否实现了某个接口
查看>>
Spring Hibernate JPA 联表查询 复杂查询(转)
查看>>
cmake 学习笔记
查看>>
获取Bootstrap-Table的所有内容,修改行内容
查看>>
【深夜福利】Caffe 添加自己定义 Layer 及其 ProtoBuffer 參数
查看>>
CATEGORICAL, ORDINAL AND INTERVAL VARIABLES
查看>>
Angular路由——路由基础
查看>>
Tomcat部署时war和war exploded的区别
查看>>
更改MySQL数据库的编码为utf8mb4
查看>>
java判断给定路径或URL下的文件或文件夹是否存在?
查看>>
java 查看线程的信息
查看>>
在CentOS7.4中安装jdk的几种方法及配置环境变量
查看>>
网络基础知识:(二)集线器、交换机和路由器
查看>>