不携带MAP结构
go
package main
import "fmt"
// ==========================
// 1. 基类(父类):Animal
// ==========================
// Animal 定义一个动物基类
// 小写字段:私有(包外无法访问,实现封装)
type Animal struct {
name string // 动物名称
age int // 年龄
}
// NewAnimal 基类构造函数(推荐写法)
func NewAnimal(name string, age int) *Animal {
return &Animal{
name: name,
age: age,
}
}
// Speak 父类方法(可被重写)
func (a *Animal) Speak() {
fmt.Printf("[Animal] %s 发出了声音\n", a.name)
}
// GetName Name getter(访问私有字段)
func (a *Animal) GetName() string {
return a.name
}
// GetAge Age getter
func (a *Animal) GetAge() int {
return a.age
}
// SetAge 设置年龄(封装私有字段修改)
func (a *Animal) SetAge(age int) {
if age > 0 {
a.age = age
}
}
// ==========================
// 2. 子类:Dog(继承 Animal)
// ==========================
// Dog 子类:嵌套 Animal 实现继承
type Dog struct {
Animal // 匿名字段 = 继承(Go 推荐组合式继承)
breed string // 品种(独有属性)
}
// NewDog 子类构造函数
func NewDog(name string, age int, breed string) *Dog {
return &Dog{
Animal: *NewAnimal(name, age), // 调用父类构造
breed: breed,
}
}
// Speak 重写父类方法(多态)
func (d *Dog) Speak() {
// 如果想调用父类方法:d.Animal.Speak()
fmt.Printf("[Dog] %s 汪汪叫!品种:%s\n", d.GetName(), d.breed)
}
// WagTail 子类独有方法
func (d *Dog) WagTail() {
fmt.Printf("[Dog] %s 正在摇尾巴~\n", d.GetName())
}
// ==========================
// 3. 另一个子类:Cat(演示多态)
// ==========================
type Cat struct {
Animal
color string
}
func NewCat(name string, age int, color string) *Cat {
return &Cat{
Animal: *NewAnimal(name, age),
color: color,
}
}
func (c *Cat) Speak() {
fmt.Printf("[Cat] %s 喵喵叫!颜色:%s\n", c.GetName(), c.color)
}
// ==========================
// 4. 接口:定义多态规范
// ==========================
type AnimalSound interface {
Speak() // 只要实现 Speak() 就算这个接口
}
// ==========================
// 主函数:使用类
// ==========================
func main() {
fmt.Println("===== 1. 创建父类 =====")
animal := NewAnimal("小生物", 2)
animal.Speak()
fmt.Println("\n===== 2. 创建子类 Dog =====")
dog := NewDog("旺财", 3, "金毛")
dog.Speak() // 调用重写方法
dog.WagTail() // 调用子类独有方法
dog.SetAge(4) // 调用父类方法
fmt.Println("修改后年龄:", dog.GetAge())
fmt.Println("\n===== 3. 创建子类 Cat =====")
cat := NewCat("咪咪", 2, "白色")
cat.Speak()
fmt.Println("\n===== 4. 多态调用(接口) =====")
animals := []AnimalSound{dog, cat}
for _, a := range animals {
a.Speak() // 自动调用各自重写的方法
}
}
携带MAP结构
go
package main
import (
"fmt"
"sync"
)
// ==========================
// 1. 基础类:动物
// ==========================
type Animal struct {
name string
age int
}
func NewAnimal(name string, age int) *Animal {
return &Animal{name: name, age: age}
}
func (a *Animal) Speak() {
fmt.Printf("【%s】 %d岁\n", a.name, a.age)
}
func (a *Animal) GetName() string { return a.name }
// ==========================
// 2. 核心:动物管理类
// ✅ map 直接写在类里面
// ✅ 锁也写在类里面
// ✅ 全部私有,外部无法乱改
//
// ==========================
type AnimalManager struct {
// 👇 map 是类的内部成员(完全封装)
animalMap map[string]*Animal
// 👇 锁也属于类(和 map 绑定)
lock sync.RWMutex
}
// 构造函数:必须初始化 map
func NewAnimalManager() *AnimalManager {
return &AnimalManager{
animalMap: make(map[string]*Animal), // 类内部初始化
}
}
// ------------------------------
// 类的方法:操作内部 map
// 外部只能通过方法调用
// ------------------------------
func (m *AnimalManager) Add(animal *Animal) {
m.lock.Lock()
defer m.lock.Unlock()
m.animalMap[animal.GetName()] = animal
}
func (m *AnimalManager) Get(name string) *Animal {
m.lock.RLock()
defer m.lock.RUnlock()
return m.animalMap[name]
}
func (m *AnimalManager) Delete(name string) {
m.lock.Lock()
defer m.lock.Unlock()
delete(m.animalMap, name)
}
func (m *AnimalManager) ShowAll() {
m.lock.RLock()
defer m.lock.RUnlock()
fmt.Println("\n==== 类内部 map 全部动物 ====")
for _, animal := range m.animalMap {
animal.Speak()
}
}
// ==========================
// 主函数:使用这个类
// ==========================
func main() {
// 1. 创建管理类(内部自带 map + 锁)
manager := NewAnimalManager()
// 2. 创建动物
a1 := NewAnimal("旺财", 3)
a2 := NewAnimal("咪咪", 2)
a3 := NewAnimal("小鸟", 1)
// 3. 交给类管理(存入类内部的 map)
manager.Add(a1)
manager.Add(a2)
manager.Add(a3)
// 4. 查看所有(遍历类内部 map)
manager.ShowAll()
// 5. 获取一个
animal := manager.Get("旺财")
if animal != nil {
fmt.Println("\n找到:")
animal.Speak()
}
// 6. 删除
manager.Delete("小鸟")
fmt.Println("\n删除后:")
manager.ShowAll()
}