【Go】Go语言继承-多态模拟

  1. 继承(结构体嵌入)
  2. 多态(接口实现和空接口)

1. 继承(结构体嵌入)

Go 语言没有传统的面向对象的继承机制,但可以通过"结构体嵌入"实现类似继承的效果。

  • 结构体嵌入:在结构体中嵌入另一个结构体,使得子结构体可以直接访问父结构体的字段和方法。
  • 字段重写 :若子结构体定义了与嵌入的结构体同名的字段,则可以认为"重写"了父结构体的同名字段,访问时默认访问子结构体自己的字段,若需要访问父结构体的字段,则使用 StructName.FieldName

代码示例:

go 复制代码
// 文件名: 03_inheritance.go
package main

import "fmt"

// 定义父类结构体 Person1
type Person1 struct {
	name string
	age  int
}

// 定义另一个父类结构体 Person2(用于展示多个继承时的处理,字段冲突时需要显式区分)
// type Person2 struct {
// 	name string
// 	age  int
// }

// 定义子类结构体 Teacher,通过嵌入 Person1 来实现继承
type Teacher struct {
	Person1 // 嵌入 Person1,实现继承
	// 如果想继承多个,则可以嵌入 Person2,但注意字段会冲突,需要通过显式调用来区分
	// Person2 // 多继承示例
	subject string
	name    int // 子类中重写了 name 字段(此字段会覆盖 Person1 中的同名字段)
}

// 为 Person1 定义一个方法
func (p *Person1) Hello() {
	fmt.Println("I am Person1....")
}

func main() {
	// 通过字面量实例化 Teacher,初始化 Person1 部分和子类特有字段
	t2 := Teacher{
		Person1: Person1{"zhangsan", 12},
		subject: "math",
	}
	fmt.Printf("t2: %+v\n", t2)
	
	// 先实例化一个 Person1 对象,然后将其赋值给 Teacher 的 Person1 字段
	p1 := Person1{"mikodo", 19}
	t3 := Teacher{Person1: p1, subject: "golang"}
	fmt.Printf("t3: %+v\n", t3)

	// 调用继承的方法
	t2.Hello()       // 等效于 t2.Person1.Hello()
	// 演示字段重写
	t2.name = 100                // 修改 Teacher 中的 name 字段(子类自己的字段)
	t2.Person1.name = "luobozi"  // 修改嵌入的 Person1 的 name 字段
	fmt.Printf("t2 after change: %+v\n", t2)
}

说明:

  • 结构体 Teacher 嵌入了 Person1,因此可以直接调用 Person1 的方法,如 Hello()
  • 子类 Teacher 定义了自己的 name 字段,这样在访问时默认访问的是 Teacher.name;如需要访问父结构体中的 name 则使用 Teacher.Person1.name

2. 多态

Go 语言多态主要通过接口(interface)实现。

  • 接口定义:接口定义了一组方法,任何实现了这些方法的类型都被视为该接口类型。
  • 鸭子类型:Go 的多态不关心具体类型,只关心是否具有接口所需的方法。
  • 空接口 :空接口 interface{} 可以表示任意类型,相当于其他语言的 Object 类型。

代码示例:

go 复制代码
// 文件名: 03_polymorphism.go
package main

import "fmt"

// 定义 MoneyPay 接口,要求实现 pay 方法
type MoneyPay interface {
	pay()
}

// 定义空接口类型(可以代表任何数据类型)
type kong interface{}

// 定义 ZFB 结构体,代表支付宝
type ZFB struct {
	name string
}

// 定义 WX 结构体,代表微信
type WX struct {
	name string
}

// 为 ZFB 绑定方法,实现 MoneyPay 接口
func (z *ZFB) pay() {
	fmt.Println("this is zfb pay")
}

// 为 WX 绑定方法,实现 MoneyPay 接口
func (w *WX) pay() {
	fmt.Println("this is wx pay")
}

// 定义函数 FinPay,接收 MoneyPay 接口类型的参数
func FinPay(p MoneyPay) {
	p.pay()
}

func main() {
	// 实例化支付宝和微信对象(均为指针类型)
	z1 := &ZFB{"支付宝"}
	w1 := &WX{"微信"}

	// 接口变量可以接收实现该接口的任何对象
	var j1, j2 MoneyPay
	j1 = z1
	j2 = w1
	fmt.Println("j1 and j2:", j1, j2)

	// 通过接口调用支付方法,实现多态
	FinPay(z1)
	FinPay(w1)

	// 空接口示例,空接口可以保存任意类型的数据
	m1 := map[string]kong{
		"name": "luobozi",
		"age":  18,
	}
	fmt.Println("空接口 map:", m1)
	
	// 类型断言:将空接口中的数据转换为具体类型,然后进行计算
	result := m1["age"].(int) + 10
	fmt.Println("断言后计算结果:", result)
}

说明:

  • 接口 MoneyPay 定义了 pay() 方法,ZFBWX 结构体分别通过指针接收者实现了该方法,从而都满足 MoneyPay 接口。
  • 函数 FinPay 接收接口类型参数,可以接受任何实现了 pay() 方法的类型,体现多态性。
  • 空接口 kong 可以存放任意数据,通过类型断言可以获取具体类型值。

总结

本篇代码整理涵盖了 Go 语言中"继承和多态"的相关知识点:

  1. 继承(结构体嵌入)

    • 利用结构体嵌入实现类似继承的效果
    • 字段重写示例:子类中定义同名字段覆盖父类字段
    • 调用嵌入结构体的方法
  2. 多态

    • 通过接口定义多态行为,只要类型实现了接口方法,就能被当作该接口类型使用
    • 演示了如何使用空接口存储任意类型数据,并通过类型断言获取具体类型
相关推荐
间彧18 分钟前
什么是Region多副本容灾
后端
爱敲代码的北19 分钟前
WPF容器控件布局与应用学习笔记
后端
爱敲代码的北19 分钟前
XAML语法与静态资源应用
后端
清空mega21 分钟前
从零开始搭建 flask 博客实验(5)
后端·python·flask
爱敲代码的北25 分钟前
UniformGrid 均匀网格布局学习笔记
后端
起予者汝也33 分钟前
Python基础入门
开发语言·python
一只叫煤球的猫1 小时前
从1996到2025——细说Java锁的30年进化史
java·后端·性能优化
芯联智造1 小时前
【stm32协议外设篇】- SU03T 智能语音模块
c语言·开发语言·stm32·单片机·嵌入式硬件
川石课堂软件测试1 小时前
Python | 高阶函数基本应用及Decorator装饰器
android·开发语言·数据库·python·功能测试·mysql·单元测试
lqqjuly1 小时前
Matlab2025a实现双目相机标定~业余版
开发语言·matlab·相机标定·双目相机