【Go语言】【15】GO语言的面向对象

原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://qingkechina.blog.51cto.com/5552198/1675872

GO是不是面向对象的语言?

GO作者如是说:“是,也不是。”

正如前面所说:GO是一种面向类型的语言,它有类型和方法,但没有类的概念,程序员可以用一种面向对象的风格(或者说是方式)来编程,下面我们从封装性、继承性和多态性三大面向对象的特性谈谈GO语言

1、封装性

       面向对象的语言中,“类”是基本单位,它把属性、方法局限在“类”中,并对外提供公共方法让使用者操作对象。当然这一过程离不开修饰符:public、protected、private等。

       GO语言如何实现封装性呢?它是通过结构体(struct)和为类型添加方法的方式实现的。

       例如,封装一个矩形(Rect)类,试想调用者会对矩形类做什么操作呢?无非就是看看它的面积、周长之类的信息,那么按照面向对象的编程思想来说,只要向使用者暴露getArea()、getPerimeter()方法即可,使用者无须接触到矩形的长和宽。


/**

  * 定义一个结构体,里面有两个成员length和width

  */

type Rect struct {

        length, width int

}

接下来为结构体定义两个方法getArea()和getPerimeter(),分别用来读取矩形的面积和周长


/**

  * 获取矩形的面积

  */

func (r *Rect) GetArea() int {

        return r.length * r.width

}

/**

  * 获取矩形的周长

  */

func (r *Rect) GetPerimeter() int {

        return (r.length + r.width) * 2

}

为了让该包之外的函数调用到GetArea()和GetPerimeter(),所以这里函数的首字母大写。同时为了结构体初始化更面向对象些,再定义一个用于初始化结构体的方法NewRect()


/**

  * 初始化结构体Rect

  */

func NewRect(length, width int) *Rect {

        return &Rect{length, width}

}

经过这样的封装,使用者可以以面向对象的方式调用Rect了 :)


/**

  * 使用者先引入Rect.go的路径

  */

import (

        "cube"

        "fmt"

)

/**

 * 通过cube调用NewRect()生成*Rect对象

 */

func main() {

        r := cube.NewRect(10, 20)

        fmt.Println("面积:", r.GetArea(), "  周长:", r.GetPerimeter())

}



【备注】:

Rect.go和测试main.go路径结构如下

其中Rect.go所属包为cube、main.go所属包为main



执行程序,运行结果如下:

2、继承性

       rect结构体定义两个方法,分别用于获取面积和周长,cube结构体也定义了两个方法,一个是获取体积,另一个重写父结构体rect的获取周长:

(1)在cube目录下创建rect.go文件,里面写rect代码


// 让rect结构体在cube包内

package cube

// 定义rect结构体

type rect struct{

        length, width int

}

/**

 * 获取矩形的面积

 */

func (r Rect) GetArea() int {

        return r.length * r.width

}

/**

 * 获取矩形的周长

 */

func (r Rect) GetPerimeter() int {

        return (r.length + r.width) * 2

}

(2)在cube目录下创建cube.go文件,里面写cube代码


// 让Cube结构体在cube包内

package cube

// 由于Cube结构体需要对外,所以首字母大写

type Cube struct {

        Rect           // 这里通过嵌套结构体实现GO的继承

        height int

}

/**

 * 获取立方体的体积

 */

func (c Cube) GetVolume() int {

        return c.Rect.length * c.Rect.width * c.height

}

/**

 * 重写父类获取周长方法

 */

func (c Cube) GetPerimeter() int {

        return (c.Rect.length + c.Rect.width + c.height) * 4

}

/**

 * 为了更象面向对象编程些,这里定义了一个方法获取Cube对象

 */

func NewCube(length, width, height int) Cube {

        return Cube{Rect: Rect{length, width}, height: height}

}

(3)在src目录下创建main.go文件,该文件与cube目录同级,里面写测试代码


// 让main()方法的包为main

package main

import (

       "cube"  // 由于要用到上面定义的Cube结构体,所以需要引入Cube结构体所属包

       "fmt"

)

func main() {

        var c cube.Cube = cube.NewCube(10, 20, 30)  // 通过包名调用cube.go定义的对外方法NewCube()

        fmt.Println("面积:", c.GetArea(), ",体积:", c.GetVolume())  // 通过变量c调用相应方法

        fmt.Println("周长:", c.GetPerimeter())

}

执行go run main.go,得到执行结果:

       从运行结果可以看到,尽管Cube没有定义GetArea()方法,但通过c.GetArea()的确调用到了同时并打印出结果;由于Cube重写了GetPerimeter()方法,从结果来看c.GetPerimeter()执行的是Cube的GetPerimeter()就去。

       从该例也不难看出GO的继承性是通过结构的嵌套来实现的

3、多态性

多态意味着一个对象有多重特征,在特定的情况下表现不同的状态,即对应着不同的方法

Mp3和Iphone都实现了USB接口,并分别实现接口USB定义的方法,当面向对象如此调用时:

USB u1 = new Mp3();

u1.connect();    // 打印出“mp3”

USB u2 = new Iphone();

u2.connect();    // 打印出“iphone”

同样的接口(USB)对象(u1, u2),由于实现类不同,调用相同的方法(connect()),最终的效果是不同的,这就是多态的作用,一般用于“控制反转”。

那么Go呢?

Go可以通过Interface、struct模拟实现多态

在src下创建usb目录,在usb目录下创建usb.go文件,里面定义USB接口


// 把接口USB放在usb包中

package usb

// 定义USB接口,里面只有一个Connect()方法

type USB interface {

        Connect()

}

在usb目录下创建mp3.go文件,里面定义Mp3结构体,并为该结构体增加Connect(),这样就相当于实现了接口USB


// 把Mp3结构体放在usb包中

package usb

import (

        "fmt"

)

// 定义Mp3空结构体

type Mp3 struct {

}

// 为Mp3增加Connect()方法,这样就缺省实现了USB接口

func (m Mp3) Connect() {

        fmt.Println("mp3")

}

同样,在usb目录下创建iphone.go文件,里面定义Iphone结构体


// 把Iphone结构体放在usb包中

package usb

import (

      "fmt"

)

// 定义Iphone空结构体

type Iphone struct {

}

// 为Iphone增加Connect()方法,这样就缺省实现了USB接口

func (i Iphone) Connect() {

        fmt.Println("iphone")

}

下面演示GO语言的多态性:

在src目录下创建main.go文件,该文件与usb目录同级,里面写测试代码


package main

import (

        "usb"

)

func main() {

        var m usb.USB = usb.Mp3{}

        m.Connect()

        var n usb.USB = usb.Iphone{}

        n.Connect()

}

执行程序,运行结果如下:



【备注】:

关于本文的演示代码可以在本章节源代码处下载


本文出自 “青客” 博客,请务必保留此出处http://qingkechina.blog.51cto.com/5552198/1675872

时间: 2024-12-05 19:48:50

【Go语言】【15】GO语言的面向对象的相关文章

C#语言与Java语言程序的比较

迈入二十一世纪以来,信息行业飞速壮大,其中在软件开发中Java语言与C#语言都独当一面,得到了逐步完善和广泛的应用,Java语言和C#语言都是一种面向对象的语言,但Java程序和C#程序还是有一定的区别. 下面分别是两种语言的程序的例子. 1.Java语言的基本程序: Import java.util.*; Package HelloJava{ Public class Message{ Public static void main(String [] args){ System.out.pr

Swift语言指南(三)--语言基础之整数和浮点数

原文:Swift语言指南(三)--语言基础之整数和浮点数   整数   整数指没有小数的整数,如42,-23.整数可以是有符号的(正数,零,负数),也可以是无符号的(正数,零). Swift提供了8,16,32,64位形式的有符号和无符号的整数,这些整数遵循与C语言相似的命名规则.如8位无符号整数的类型为UInt8,32位有符号整数的类型为Int32,和Swift语言的其它类型一样,这些整型命名以大写字母开头.   整数的边界 你可以通过min或max属性为每一个整数类型指定一个最小值或最大值:

《OOD启思录》—第1章1.5节造原型:相同语言与不同语言

1.5 构造原型:相同语言与不同语言OOD启思录原型领域可划分为两大流派.一派认为原型与最终产品应当用同一种语言编写(same-language prototyping),另一派认为原型与最终产品应当用不同的语言编写(different-language prototyping).相同语言原型带来的好处看起来简直无法拒绝:使用同一种语言,这意味着同一套工具,相同的参考书,相同的学习曲线,相同的培训课程.一点也不奇怪,这两大流派中相同语言原型被更多地运用. 最后的原型终将成为产品.这一模型的主要缺

Java语言与C++语言的差异总结

Java的设计者曾说过,设计这门语言的灵感主要来自于C++. 世上先有C++,然后才有Java,整个Java语言的发展历史就是一部对C++的填坑史.所以在Java语言学习过程中,将其与C++语言对比是一件有意义的事情.通过这些对比,我们能够了解到Java语言相对于C++语言有哪些改进,能带给我们哪些进步,这样对于更加深入理解这两种语言是大有裨益的. 下面我总结一下Java语言与C++语言的各种差异. 1.Java用来操纵对象的引用可以先初始化再指向对象,而C++的引用必须在初始化时就指向对象.

Thinkphp搭建包括JS多语言的多语言项目实现方法_php实例

本文实例讲述了Thinkphp搭建包括JS多语言的多语言项目实现方法.分享给大家供大家参考.具体实现方法如下: 一.问题: 项目需要开发英文版,于是需要搭建多语言项目. 项目使用Thinkphp框架,隐约记得Thinkphp有多语言设置,翻看了帮助手册,果然有,这就边实验边开始: 二.实现方法: Thinkphp采用app_begain来检测和切换语言包,语言包和项目相关,构架等都比较简单,具体的这里:http://www.thinkphp.cn/info/188.html 搭建好了,就可以使用

r语言-对一个向量的划分,求C语言或R语言实现

问题描述 对一个向量的划分,求C语言或R语言实现 1C 向量U={123456}利用R1属性划分为:U/R1={{123}{456}}利用R2属性划分为:U/R2={{12}{3456}}利用R3属性划分为:U/R3={{1234}{56}}最后得到划分的交集:U/R={{12}{3}{4}{56}}

Swift语言指南(一)--语言基础之常量和变量

原文:Swift语言指南(一)--语言基础之常量和变量 Swift 是开发 iOS 及 OS X 应用的一门新编程语言,然而,它的开发体验与 C 或 Objective-C 有很多相似之处. Swift 提供了 C 与 Objective-C 中的所有基础类型,包括表示整数的 Int,表示浮点数的 Double 与 Float,表示布尔值的 Bool,以及表示纯文本数据的 String. Swift 还为两个基本集合类型 Array 与 Dictionary 提供了强大的支持,详情可参考 (集合

各国语言缩写列表,各国语言缩写-各国语言简称,世界各国域名缩写

$amount = '12345.67'; $formatter = new \NumberFormatter('en_GB', \NumberFormatter::CURRENCY); echo 'UK: ' . $formatter->formatCurrency($amount, 'EUR') . '<br/>'; $formatter = new \NumberFormatter('de_DE', \NumberFormatter::CURRENCY); echo 'DE: '

c语言与c++语言之间的相互转化

问题描述 c语言与c++语言之间的相互转化 struct student*p0 scanf("%s",p0->num) scanf("%s",&p0->name) 解决方案 C++也能兼容C,直接编译看有没有什么语法错误 解决方案二: 对的,C++编译器本来就支持几乎所有C语法 你为何还需要改 C --> C++ #include scanf("%s",p0->num); --> std::cin >&

c语言-C语言递归函数C语言递归函数C语言递归函数

问题描述 C语言递归函数C语言递归函数C语言递归函数 #include<stdio.h> #include<stdlib.h> //用递归函数来计算N的阶乘 double factorial(int n) { double result; if(n<0) { printf("输入错误 "); } else if(n==1 ||n==0) { result=1; } else { result=factorial(n-1)*n; //n=5 5-1=4 4*