数据结构和算法-Go泛型实现:第三章抽象数据类型:Go 中的面向对象编程-1. 使用类实现抽象数据类型

70 阅读2分钟

第三章:抽象数据类型:Go 中的面向对象编程

1. 使用类实现抽象数据类型

在面向对象编程(OOP)中,抽象数据类型(ADT)是指通过封装和抽象来定义数据和操作的一种方法。虽然 Go 语言没有直接的类和继承机制,但我们可以通过结构体和接口来实现类似于 OOP 的功能,从而实现抽象数据类型。

Go 中的抽象数据类型实现

示例:实现一个计数器 ADT

我们将创建一个计数器(Counter)类型,该类型将包含一个内部计数器变量以及操作该变量的方法。

1. 定义 Counter 结构体

package main

import (
	"fmt"
)

// Counter 结构体,包含一个私有的计数器变量
type Counter struct {
	count int
}

// NewCounter 返回一个新的 Counter 实例
func NewCounter() *Counter {
	return &Counter{count: 0}
}

// Increment 增加计数器的值
func (c *Counter) Increment() {
	c.count++
}

// Decrement 减少计数器的值
func (c *Counter) Decrement() {
	c.count--
}

// GetValue 返回当前计数器的值
func (c *Counter) GetValue() int {
	return c.count
}

2. 使用 Counter 结构体

func main() {
	counter := NewCounter()
	counter.Increment()
	fmt.Println("Counter value after increment:", counter.GetValue())
	counter.Decrement()
	fmt.Println("Counter value after decrement:", counter.GetValue())
}
使用接口定义抽象数据类型

我们可以通过接口来定义抽象数据类型,从而为不同的实现提供统一的操作方法。

示例:使用接口定义一个 Stack ADT

1. 定义 Stack 接口

package main

import (
	"errors"
	"fmt"
)

// Stack 接口,定义了栈的操作方法
type Stack[T any] interface {
	Push(value T)
	Pop() (T, error)
	Peek() (T, error)
	IsEmpty() bool
}

2. 实现一个基于切片的 Stack

// SliceStack 基于切片的栈实现
type SliceStack[T any] struct {
	items []T
}

// NewSliceStack 返回一个新的 SliceStack 实例
func NewSliceStack[T any]() *SliceStack[T] {
	return &SliceStack[T]{items: []T{}}
}

// Push 将元素压入栈中
func (s *SliceStack[T]) Push(value T) {
	s.items = append(s.items, value)
}

// Pop 从栈中弹出元素
func (s *SliceStack[T]) Pop() (T, error) {
	if s.IsEmpty() {
		var zero T
		return zero, errors.New("stack is empty")
	}
	value := s.items[len(s.items)-1]
	s.items = s.items[:len(s.items)-1]
	return value, nil
}

// Peek 查看栈顶元素
func (s *SliceStack[T]) Peek() (T, error) {
	if s.IsEmpty() {
		var zero T
		return zero, errors.New("stack is empty")
	}
	return s.items[len(s.items)-1], nil
}

// IsEmpty 判断栈是否为空
func (s *SliceStack[T]) IsEmpty() bool {
	return len(s.items) == 0
}

3. 使用 Stack 接口和 SliceStack 实现

func main() {
	stack := NewSliceStack[int]()
	stack.Push(10)
	stack.Push(20)
	value, _ := stack.Pop()
	fmt.Println("Popped value:", value)
	value, _ = stack.Peek()
	fmt.Println("Peek value:", value)
	fmt.Println("Is stack empty?", stack.IsEmpty())
}

通过以上示例,我们展示了如何使用结构体和接口来实现抽象数据类型,从而模拟 Go 语言中的面向对象编程。通过这种方式,我们可以创建可重用、可扩展的代码,并实现复杂的数据结构和算法。