Go父类调用子类方法(虚函数调用)

ops/2024/10/18 23:28:07/

前言

在Go语言中,支持组合而不是继承。网上都说可以通过接口和结构体内嵌来模拟面向对象编程中的子类和父类关系。但给的例子或写法感觉都不是很好,难以达到我的目的(比如通过模板模式实现代码的重用等)。因此调查了一下实现方式。

结论

  • 可以通过定义 interface + 组合接口变量 + NewXxx 函数中对接口变量赋值(类似于给 this 变量赋值) 的方式实现 Go 的继承和虚函数调用。废话少说, 直接上代码。
// 定义一个表示形状的 Shape 接口
type Shape interface {Name() stringArea() float64      //求面积Perimeter() float64 //求周长String() string
}// 定义实现了部分业务逻辑的抽象基类
type BaseShape struct {Shape // 组合了接口,因此有了其接口的方法声明, 注意: 其值为 nil, 需要在子类的 NewXxx 中对其赋值(相当于设置为 this)name  string
}func (bs BaseShape) Name() string {return bs.name
}func (bs BaseShape) AbstractMethod() string {return "base"
}// 此处在 BaseShape 的 String() 方法中调用子类会重载的 Area()/Perimeter() 方法
func (bs BaseShape) String() string {if bs.Shape == nil {// 由于需要手动设置 Shape 的值(不像 C++ 可以在 new 时自动设置), 为了在 nil panic 的时候有更好的提示, 此处主动 panic,提醒这种编码错误panic(fmt.Sprintf("must set Shape in child struct 's new function, name=%s", bs.name))}//这里既可以通过 bs.Xxx() 调用, 也可以通过 bs.Shape.Xxx() 调用.return fmt.Sprintf("name=%s: absMethod=%s, area=%f, perimeter=%f",bs.Name(), bs.AbstractMethod(), bs.Shape.Area(), bs.Shape.Perimeter())
}type Rect struct {BaseShapeWidth  float64Height float64
}func (r *Rect) Area() float64 {return r.Width * r.Height
}
func (r *Rect) Perimeter() float64 {return 2 * (r.Width + r.Height)
}func (r *Rect) AbstractMethod() string {return "abs_rect"
}func NewRect(width, height float64) *Rect {rect := &Rect{BaseShape: BaseShape{name: "rect"},Width:     width,Height:    height,}rect.Shape = rect // 将 BaseShape 中的 Shape 变量设置为 this,父类才可以调用return rect
}type Square struct {Rect
}func NewSquare(sides float64) *Square {square := &Square{Rect{BaseShape: BaseShape{name: "square"},Height:    sides,Width:     sides,}}square.Shape = squarereturn square
}
type Circle struct {BaseShapeRadius float64
}func (c *Circle) Area() float64 {return math.Pi * c.Radius * c.Radius
}
func (c *Circle) Perimeter() float64 {return 2 * math.Pi * c.Radius
}func (c *Circle) AbstractMethod() string {return "abs_circle"
}func NewCircle(radius float64) *Circle {circle := &Circle{BaseShape: BaseShape{name: "circle"},Radius:    radius,}circle.Shape = circle //将 BaseShape 中的 Shape 变量设置为 this,父类才可以调用return circle
}

以上代码实现了如下的继承结构,可以将 String() 方法看成业务方法,其中调用子类提供实现的抽象方法。
在这里插入图片描述

测试代码

通过 shape 变量的 String() 方法调用了子类的 Name()/Area()/Perimeter() 等方法.

func TestVirtualFunctionCall(t *testing.T) {var rect Shape = NewRect(10, 20)var circle Shape = NewCircle(10)var square Shape = NewSquare(10)assert.Equal(t, "name=rect: absMethod=base, area=200.000000, perimeter=60.000000", rect.String())assert.Equal(t, "name=square: absMethod=base, area=100.000000, perimeter=40.000000", square.String())assert.Equal(t, "name=circle: absMethod=base, area=314.159265, perimeter=62.831853", circle.String())
}

补充说明

  • 通过这种方法,可以成功的在 Go 语言中实现 多态,虚函数 等 C++/Java 才有的概念,从而可以想办法实现各种设计模式,大大提高项目质量。
  • 但也存在一些限制,比如:
    • 无法在 BaseShape 中再次定义一些虚函数由子类实现并调用(参考 AbstractMethod),如想要其也是虚函数的样子,必须也定义到 interface 中.

http://www.ppmy.cn/ops/105094.html

相关文章

基于LDA模型的经济金融政策文本研究与分析设计与实现,很详细

摘 要 经济金融政策文本的研究与分析对于理解国家经济发展方向和政策制定逻辑至关重要。近年来,随着信息技术的发展,基于文本的定量分析方法在经济金融领域得到广泛应用。LDA(Latent Dirichlet Allocation)作为一种典型的主题模型…

SpringBoot SSM vue在线作业考试系统

SpringBoot SSM vue在线作业考试系统 首页 图片轮播 作业信息 通知公告 登录注册 留言板 个人中心 我的收藏 后台管理 登录注册 个人中心 教师信息管理 学生信息管理 学院信息管理 专业信息管理 班级信息管理 作业信息管理 作业提交管理 通知公告管理 试卷管理 试题管理 系统…

jenkins

jenkins简介 Jenkins是一个开源CI&CD软件、提供友好操作界面的持续集成(CI)工具; 起源于Hudson(Hudson是商用的),主要用于持续、自动的构建/测试软件项目、监控外部任务的运行;Jenkins用J…

使用 ip route 命令配置 Linux 路由表的详细指南

深入解析 Linux 路由表及其配置 在现代计算机网络中,路由表是网络通信的核心组成部分。Linux 作为一种广泛使用的操作系统,在路由表管理方面提供了强大的工具集。本文将详细介绍 Linux 路由表的基本概念、查看与配置方法,以及如何通过实际案…

【HarmonyOS】模仿个人中心头像图片,调用系统相机拍照,从系统相册选择图片和圆形裁剪显示 (一)

【HarmonyOS】头像图片,调用系统相机拍照,从系统相册选择图片和圆形裁剪显示 (一) Demo效果展示: 方案思路: 使用photoAccessHelper实现系统相册选择图片的功能。此API可在无需用户授权的情况下&#xff…

整数算术运算中的错误

如果一个整数被零除,将不会产生正确的结果,而是出现一个异常( exception ).在Java中,异常是标志错误的一种方法,我们将在第7章中详细地介绍。对变量或表达式应用%运算符,如果右侧的操作数是零&a…

【什么是电商供应链】

文章目录 前言一、商品来源与采购计划:二、商品信息与库存管理:三、订单处理与物流配送:四、金融服务与全球采购:总结 前言 电商供应链是将传统供应链电子商务化,通过互联网服务平台实现供应链交易过程的全程电子化&a…

AI人数智能统计监测摄像头

随着人工智能技术的不断发展,AI人数智能统计监测摄像头 在各个领域得到了广泛应用。这种摄像头结合了图像识别技术和智能算法,旨在实现对人群数量的准确统计和监测。通过高清晰度的摄像头捕捉到场景中的人群图像,并通过人工智能技术进行快速准…