Golang 面向对象编程,如何实现 封装、继承、多态

Go语言虽然不是纯粹的面向对象语言,但它通过结构体(struct)、接口(interface)和方法(method)提供了面向对象编程的能力。下面我将通过具体示例展示Go中如何实现类、封装、继承、多态以及构造函数等概念。

1. 类与封装

在Go中,使用结构体(struct)来定义"类",并通过大小写控制访问权限实现封装。 

package main

import "fmt"

// Person 类(结构体)
type Person struct {
    name string // 小写开头,私有字段(仅在当前包内可访问)
    Age  int    // 大写开头,公共字段(可在其他包中访问)
}

// NewPerson 构造函数(工厂函数)
// 通常以New开头命名构造函数
func NewPerson(name string, age int) *Person {
    return &Person{
        name: name,
        Age:  age,
    }
}

// GetName 获取name的方法(Getter)
// 由于name是私有的,需要通过方法访问
func (p *Person) GetName() string {
    return p.name
}

// SetName 设置name的方法(Setter)
func (p *Person) SetName(name string) {
    p.name = name
}

// Introduce 方法
func (p *Person) Introduce() {
    fmt.Printf("大家好,我是%s,今年%d岁。\n", p.name, p.Age)
}

func main() {
    // 使用构造函数创建Person实例
    person := NewPerson("张三", 25)
    
    // 访问公共字段
    fmt.Println("年龄:", person.Age)
    
    // 通过方法访问私有字段
    fmt.Println("姓名:", person.GetName())
    
    // 修改私有字段
    person.SetName("李四")
    
    // 调用方法
    person.Introduce()
}

2. 继承(组合) 

 Go没有传统意义上的继承,而是通过结构体嵌入(embedding)实现组合。

package main

import "fmt"

// Animal 基类
type Animal struct {
    name string
}

// NewAnimal 构造函数
func NewAnimal(name string) *Animal {
    return &Animal{name: name}
}

// Speak 方法
func (a *Animal) Speak() {
    fmt.Println(a.name, "发出声音")
}

// Eat 方法
func (a *Animal) Eat() {
    fmt.Println(a.name, "正在吃东西")
}

// Dog 继承Animal
type Dog struct {
    *Animal          // 嵌入Animal,相当于继承
    Breed   string  // 狗的品种
}

// NewDog 构造函数
func NewDog(name, breed string) *Dog {
    return &Dog{
        Animal: NewAnimal(name),
        Breed:  breed,
    }
}

// Speak 方法重写
func (d *Dog) Speak() {
    fmt.Println(d.name, "汪汪叫")
}

// Fetch 子类特有方法
func (d *Dog) Fetch() {
    fmt.Println(d.name, "正在捡球")
}

func main() {
    animal := NewAnimal("普通动物")
    animal.Speak()
    animal.Eat()
    
    dog := NewDog("阿黄", "金毛")
    dog.Speak()    // 调用重写后的方法
    dog.Eat()      // 调用继承的方法
    dog.Fetch()    // 调用子类特有方法
    
    // 通过嵌入字段访问基类字段
    fmt.Println("狗的名字:", dog.name)
    fmt.Println("狗的品种:", dog.Breed)
}

 3. 多态(接口实现)

Go通过接口(interface)实现多态。

package main

import "fmt"

// Shape 接口
type Shape interface {
    Area() float64
    Perimeter() float64
}

// Rectangle 矩形类
type Rectangle struct {
    width, height float64
}

// NewRectangle 构造函数
func NewRectangle(width, height float64) *Rectangle {
    return &Rectangle{width, height}
}

// Area 实现Shape接口的方法
func (r *Rectangle) Area() float64 {
    return r.width * r.height
}

// Perimeter 实现Shape接口的方法
func (r *Rectangle) Perimeter() float64 {
    return 2 * (r.width + r.height)
}

// Circle 圆形类
type Circle struct {
    radius float64
}

// NewCircle 构造函数
func NewCircle(radius float64) *Circle {
    return &Circle{radius}
}

// Area 实现Shape接口的方法
func (c *Circle) Area() float64 {
    return 3.14 * c.radius * c.radius
}

// Perimeter 实现Shape接口的方法
func (c *Circle) Perimeter() float64 {
    return 2 * 3.14 * c.radius
}

// PrintShapeInfo 多态函数,接受任何实现了Shape接口的类型
func PrintShapeInfo(s Shape) {
    fmt.Printf("面积: %.2f, 周长: %.2f\n", s.Area(), s.Perimeter())
}

func main() {
    rect := NewRectangle(10, 5)
    circle := NewCircle(7)
    
    // 相同接口,不同表现
    PrintShapeInfo(rect)
    PrintShapeInfo(circle)
    
    // 接口类型断言
    if r, ok := rect.(*Rectangle); ok {
        fmt.Println("这是一个矩形,宽:", r.width, "高:", r.height)
    }
    
    // 类型开关(type switch)
    var s Shape = circle
    switch v := s.(type) {
    case *Rectangle:
        fmt.Println("矩形:", v.width, v.height)
    case *Circle:
        fmt.Println("圆形,半径:", v.radius)
    default:
        fmt.Println("未知形状")
    }
}

 4. 方法实现细节

Go中的方法可以绑定到任何类型(不仅仅是结构体),包括基本类型。 

package main

import (
    "fmt"
    "math"
)

// MyInt 自定义类型
type MyInt int

// Double 方法
func (m MyInt) Double() MyInt {
    return m * 2
}

// Point 结构体
type Point struct {
    X, Y float64
}

// DistanceTo 方法(值接收者)
func (p Point) DistanceTo(q Point) float64 {
    return math.Hypot(q.X-p.X, q.Y-p.Y)
}

// Scale 方法(指针接收者,会修改原值)
func (p *Point) Scale(factor float64) {
    p.X *= factor
    p.Y *= factor
}

// String 方法(实现Stringer接口)
func (p Point) String() string {
    return fmt.Sprintf("Point{X: %.2f, Y: %.2f}", p.X, p.Y)
}

func main() {
    // 自定义类型方法
    num := MyInt(5)
    fmt.Println(num.Double()) // 10
    
    // 结构体方法
    p1 := Point{1, 2}
    p2 := Point{4, 6}
    
    fmt.Println("距离:", p1.DistanceTo(p2)) // 5
    
    p1.Scale(2)
    fmt.Println(p1) // 使用String方法输出: Point{X: 2.00, Y: 4.00}
    
    // 指针与值的自动转换
    p3 := &Point{3, 4}
    fmt.Println("距离:", p3.DistanceTo(p2)) // Go会自动解引用
    
    p2.Scale(0.5) // Go会自动取地址
    fmt.Println(p2)
}

 5. 综合示例

package main

import (
    "fmt"
    "strings"
)

// Employee 基类
type Employee struct {
    name     string
    salary   float64
    vacation bool
}

// NewEmployee 构造函数
func NewEmployee(name string, salary float64) *Employee {
    return &Employee{
        name:     name,
        salary:   salary,
        vacation: false,
    }
}

// GetName Getter
func (e *Employee) GetName() string {
    return e.name
}

// GetSalary Getter
func (e *Employee) GetSalary() float64 {
    return e.salary
}

// TakeVacation 方法
func (e *Employee) TakeVacation() {
    e.vacation = true
}

// Work 方法
func (e *Employee) Work() {
    fmt.Printf("%s 正在工作...\n", e.name)
}

// String 方法
func (e *Employee) String() string {
    return fmt.Sprintf("员工: %s, 薪资: %.2f, 休假中: %v", 
        e.name, e.salary, e.vacation)
}

// Developer 子类
type Developer struct {
    *Employee         // 嵌入Employee
    language  string // 开发语言
}

// NewDeveloper 构造函数
func NewDeveloper(name string, salary float64, language string) *Developer {
    return &Developer{
        Employee: NewEmployee(name, salary),
        language: language,
    }
}

// Work 方法重写
func (d *Developer) Work() {
    fmt.Printf("%s 正在用 %s 写代码...\n", d.GetName(), d.language)
}

// Debug 特有方法
func (d *Developer) Debug() {
    fmt.Printf("%s 正在调试 %s 代码...\n", d.GetName(), d.language)
}

// Manager 子类
type Manager struct {
    *Employee        // 嵌入Employee
    team      []string // 团队成员
}

// NewManager 构造函数
func NewManager(name string, salary float64, team []string) *Manager {
    return &Manager{
        Employee: NewEmployee(name, salary),
        team:     team,
    }
}

// Work 方法重写
func (m *Manager) Work() {
    fmt.Printf("%s 正在管理团队: %s\n", 
        m.GetName(), strings.Join(m.team, ", "))
}

// ConductMeeting 特有方法
func (m *Manager) ConductMeeting() {
    fmt.Printf("%s 正在主持会议\n", m.GetName())
}

// Worker 接口
type Worker interface {
    Work()
    GetName() string
    GetSalary() float64
}

// Company 公司类
type Company struct {
    workers []Worker
}

// AddWorker 添加员工
func (c *Company) AddWorker(w Worker) {
    c.workers = append(c.workers, w)
}

// StartWorkDay 开始工作日
func (c *Company) StartWorkDay() {
    fmt.Println("===== 工作日开始 =====")
    for _, worker := range c.workers {
        worker.Work()
    }
    fmt.Println("===== 工作日结束 =====")
}

func main() {
    // 创建公司
    company := &Company{}
    
    // 创建员工
    dev1 := NewDeveloper("张三", 15000, "Go")
    dev2 := NewDeveloper("李四", 16000, "Python")
    manager := NewManager("王五", 25000, []string{"张三", "李四"})
    
    // 员工休假
    dev1.TakeVacation()
    
    // 添加员工到公司
    company.AddWorker(dev1)
    company.AddWorker(dev2)
    company.AddWorker(manager)
    
    // 开始工作
    company.StartWorkDay()
    
    // 调用特有方法
    dev2.Debug()
    manager.ConductMeeting()
    
    // 打印员工信息
    fmt.Println(dev1)
    fmt.Println(dev2)
    fmt.Println(manager)
}

关键概念总结

  1. 类与封装:Go使用结构体定义类,通过字段/方法名的大小写控制访问权限(大写公开,小写私有)

  2. 构造函数:Go没有真正的构造函数,通常使用NewXxx形式的工厂函数

  3. 继承:通过结构体嵌入实现组合式继承

  4. 多态:通过接口实现,任何实现了接口所有方法的类型都自动满足该接口

  5. 方法:可以绑定到任何类型,接收者可以是值或指针

  6. 接口:定义行为而非实现,是实现多态的关键

Go的面向对象方式与传统OOP语言有所不同,它更强调组合而非继承,通过接口实现多态,这种方式更灵活且避免了传统继承的许多问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值