embedding.go
文件信息
- 📄 原文件:
03_embedding.go - 🔤 语言:go
完整代码
go
package main
import "fmt"
// ============================================================
// 类型嵌入与组合
// ============================================================
// Go 推崇组合(composition)而非继承(inheritance)
// 通过嵌入类型实现代码复用
func main03() {
fmt.Println("\n==================== 03_embedding ====================")
fmt.Println("=== 结构体嵌入 ===")
// ----------------------------------------------------------
// 基本嵌入
// ----------------------------------------------------------
dog := Dog{
Animal: Animal{Name: "旺财", Age: 3},
Breed: "金毛",
}
// 字段提升:直接访问嵌入类型的字段
fmt.Println("名字:", dog.Name) // 等价于 dog.Animal.Name
fmt.Println("年龄:", dog.Age) // 等价于 dog.Animal.Age
fmt.Println("品种:", dog.Breed)
// 方法提升:直接调用嵌入类型的方法
dog.Eat() // 调用 Animal.Eat()
dog.Sleep() // 调用 Animal.Sleep()
dog.Bark() // Dog 自己的方法
// ----------------------------------------------------------
// 方法覆盖
// ----------------------------------------------------------
fmt.Println("\n=== 方法覆盖 ===")
cat := Cat{
Animal: Animal{Name: "咪咪", Age: 2},
}
cat.Speak() // 调用 Cat.Speak()(覆盖了 Animal.Speak)
cat.Animal.Speak() // 显式调用被覆盖的方法
// ----------------------------------------------------------
// 多重嵌入
// ----------------------------------------------------------
fmt.Println("\n=== 多重嵌入 ===")
super := SuperHero{
Person2: Person2{Name: "彼得·帕克", Age: 18},
Powers: Powers{Flight: false, Strength: true, Speed: true},
Alias: "蜘蛛侠",
}
fmt.Printf("英雄: %s (%s)\n", super.Alias, super.Name)
fmt.Printf("能力: 飞行=%t, 力量=%t, 速度=%t\n",
super.Flight, super.Strength, super.Speed)
super.Introduce()
// ----------------------------------------------------------
// 嵌入接口
// ----------------------------------------------------------
fmt.Println("\n=== 嵌入接口 ===")
logger := &FileLogger{filename: "app.log"}
app := &Application{
Logger: logger,
Name: "MyApp",
}
// 通过嵌入的接口调用方法
app.Log("应用启动")
app.Log("处理请求")
// ----------------------------------------------------------
// 嵌入指针
// ----------------------------------------------------------
fmt.Println("\n=== 嵌入指针 ===")
base := &Base{ID: 1}
derived := Derived{
Base: base,
Extra: "额外数据",
}
fmt.Println("ID:", derived.ID)
derived.PrintID()
// 【注意】嵌入指针可能为 nil
var d2 Derived
// d2.PrintID() // panic! Base 是 nil
if d2.Base != nil {
d2.PrintID()
} else {
fmt.Println("Base 为 nil,跳过")
}
// ----------------------------------------------------------
// 组合 vs 继承
// ----------------------------------------------------------
fmt.Println("\n=== 组合 vs 继承 ===")
// 组合方式1:嵌入
e1 := Engine{Power: 200}
car1 := CarEmbed{Engine: e1, Brand: "Tesla"}
car1.Start() // 直接调用
// 组合方式2:字段
car2 := CarField{engine: Engine{Power: 150}, Brand: "BMW"}
car2.engine.Start() // 通过字段调用
car2.Start() // 包装方法
// ----------------------------------------------------------
// 实际应用:装饰器模式
// ----------------------------------------------------------
fmt.Println("\n=== 装饰器模式 ===")
// 基础计数器
var counter Counter = &BasicCounter{}
// 添加日志装饰
counter = &LoggingCounter{Counter: counter}
// 添加线程安全装饰(示意)
// counter = &ThreadSafeCounter{Counter: counter}
counter.Increment()
counter.Increment()
fmt.Println("计数:", counter.Value())
}
// ============================================================
// 类型定义
// ============================================================
// ----------------------------------------------------------
// 基本嵌入示例
// ----------------------------------------------------------
// Animal 动物基类
type Animal struct {
Name string
Age int
}
func (a Animal) Eat() {
fmt.Printf("%s 正在吃东西\n", a.Name)
}
func (a Animal) Sleep() {
fmt.Printf("%s 正在睡觉\n", a.Name)
}
func (a Animal) Speak() {
fmt.Printf("%s 发出声音\n", a.Name)
}
// Dog 狗(嵌入 Animal)
type Dog struct {
Animal // 嵌入
Breed string
}
func (d Dog) Bark() {
fmt.Printf("%s 汪汪叫\n", d.Name)
}
// Cat 猫(嵌入 Animal,覆盖 Speak)
type Cat struct {
Animal
}
// Speak 覆盖 Animal 的 Speak 方法
func (c Cat) Speak() {
fmt.Printf("%s 喵喵叫\n", c.Name)
}
// ----------------------------------------------------------
// 多重嵌入
// ----------------------------------------------------------
type Person2 struct {
Name string
Age int
}
type Powers struct {
Flight bool
Strength bool
Speed bool
}
// SuperHero 多重嵌入
type SuperHero struct {
Person2 // 嵌入 Person
Powers // 嵌入 Powers
Alias string
}
func (s SuperHero) Introduce() {
fmt.Printf("我是 %s,也被称为 %s\n", s.Name, s.Alias)
}
// ----------------------------------------------------------
// 嵌入接口
// ----------------------------------------------------------
// Logger 日志接口
type Logger interface {
Log(message string)
}
// FileLogger 文件日志实现
type FileLogger struct {
filename string
}
func (f *FileLogger) Log(message string) {
fmt.Printf("[%s] %s\n", f.filename, message)
}
// Application 应用(嵌入 Logger 接口)
type Application struct {
Logger // 嵌入接口
Name string
}
// ----------------------------------------------------------
// 嵌入指针
// ----------------------------------------------------------
type Base struct {
ID int
}
func (b *Base) PrintID() {
fmt.Println("Base ID:", b.ID)
}
type Derived struct {
*Base // 嵌入指针
Extra string
}
// ----------------------------------------------------------
// 组合 vs 继承对比
// ----------------------------------------------------------
type Engine struct {
Power int
}
func (e Engine) Start() {
fmt.Printf("引擎启动 (功率: %d)\n", e.Power)
}
// CarEmbed 使用嵌入
type CarEmbed struct {
Engine // 嵌入
Brand string
}
// CarField 使用字段
type CarField struct {
engine Engine // 字段
Brand string
}
func (c CarField) Start() {
fmt.Printf("%s 汽车: ", c.Brand)
c.engine.Start()
}
// ----------------------------------------------------------
// 装饰器模式示例
// ----------------------------------------------------------
// Counter 计数器接口
type Counter interface {
Increment()
Value() int
}
// BasicCounter 基础实现
type BasicCounter struct {
count int
}
func (c *BasicCounter) Increment() {
c.count++
}
func (c *BasicCounter) Value() int {
return c.count
}
// LoggingCounter 带日志的装饰器
type LoggingCounter struct {
Counter // 嵌入接口
}
func (c *LoggingCounter) Increment() {
fmt.Println("[LOG] Increment 被调用")
c.Counter.Increment() // 调用被装饰的对象
}
// ============================================================
// 重要注意事项
// ============================================================
//
// 1. 【嵌入 ≠ 继承】
// - 嵌入是组合,不是继承
// - 没有 super 关键字
// - 被嵌入类型不知道外部类型
//
// 2. 【字段/方法提升】
// 嵌入类型的字段和方法会提升到外层
// 可以直接访问,无需通过嵌入字段名
//
// 3. 【命名冲突】
// - 外层字段/方法优先级更高
// - 多个嵌入类型有相同名称时,必须显式指定
//
// 4. 【嵌入指针注意】
// - 嵌入指针可能为 nil
// - 调用方法前应检查
//
// 5. 【何时使用嵌入】
// - 代码复用(共享字段和方法)
// - 实现接口
// - 装饰器模式
//
// 6. 【何时使用字段】
// - 不想暴露内部实现
// - 需要更细粒度的控制
// - 避免命名冲突
//
// 7. 【设计原则】
// "组合优于继承"
// 通过小接口和嵌入实现灵活的代码复用
💬 讨论
使用 GitHub 账号登录后即可参与讨论