Skip to content

面向对象

虽然 Lua 不是一种纯面向对象的语言,但它提供了一些机制来实现面向对象编程。本章节将介绍 Lua 中面向对象编程的基本概念和实现方法。

基本概念

在 Lua 中,面向对象编程通常使用表和元表来实现:

  • :使用表来表示
  • 对象:类的实例,也是表
  • 方法:表中的函数
  • 继承:使用元表实现

类的定义

示例:定义一个 Person 类

lua
local Person = {}
Person.__index = Person

function Person:new(name, age)
  local obj = {}
  setmetatable(obj, self)
  obj.name = name
  obj.age = age
  return obj
end

function Person:sayHello()
  print("Hello, my name is " .. self.name)
end

function Person:getAge()
  return self.age
end

对象的创建和使用

lua
local person = Person:new("张三", 30)
person:sayHello()  -- 输出 Hello, my name is 张三
print(person:getAge())  -- 输出 30

继承

示例:定义一个 Student 类继承自 Person 类

lua
local Student = {}
Student.__index = Student
setmetatable(Student, Person)

function Student:new(name, age, studentId)
  local obj = Person:new(name, age)
  setmetatable(obj, self)
  obj.studentId = studentId
  return obj
end

function Student:study()
  print(self.name .. " is studying")
end

function Student:sayHello()
  print("Hello, I'm a student, my name is " .. self.name)
end
lua
local student = Student:new("李四", 20, "123456")
student:sayHello()  -- 输出 Hello, I'm a student, my name is 李四
student:study()  -- 输出 李四 is studying
print(student:getAge())  -- 输出 20,继承自 Person 类

封装

在 Lua 中,可以使用局部变量和函数来实现封装:

lua
local Person = {}
Person.__index = Person

-- 私有变量
local privateVariable = "私有变量"

-- 私有函数
local function privateFunction()
  print("这是一个私有函数")
end

function Person:new(name, age)
  local obj = {}
  setmetatable(obj, self)
  obj.name = name
  obj.age = age
  return obj
end

function Person:sayHello()
  privateFunction()  -- 调用私有函数
  print("Hello, my name is " .. self.name)
end

多态

在 Lua 中,多态是通过方法重写实现的:

lua
local Animal = {}
Animal.__index = Animal

function Animal:new(name)
  local obj = {}
  setmetatable(obj, self)
  obj.name = name
  return obj
end

function Animal:speak()
  print("动物发出声音")
end

local Dog = {}
Dog.__index = Dog
setmetatable(Dog, Animal)

function Dog:new(name)
  return Animal.new(self, name)
end

function Dog:speak()
  print("汪汪汪")
end

local Cat = {}
Cat.__index = Cat
setmetatable(Cat, Animal)

function Cat:new(name)
  return Animal.new(self, name)
end

function Cat:speak()
  print("喵喵喵")
end

-- 多态
function makeAnimalSpeak(animal)
  animal:speak()
end

local dog = Dog:new("旺财")
local cat = Cat:new("汤姆")

makeAnimalSpeak(dog)  -- 输出 汪汪汪
makeAnimalSpeak(cat)  -- 输出 喵喵喵

构造函数和析构函数

构造函数

在 Lua 中,构造函数通常命名为 new

lua
function Person:new(name, age)
  local obj = {}
  setmetatable(obj, self)
  obj.name = name
  obj.age = age
  -- 初始化代码
  return obj
end

析构函数

在 Lua 中,可以使用 __gc 元方法实现析构函数:

lua
local Person = {}
Person.__index = Person

function Person:new(name, age)
  local obj = {}
  setmetatable(obj, self)
  obj.name = name
  obj.age = age
  return obj
end

function Person:__gc()
  print("Person 对象被销毁:" .. self.name)
end

local person = Person:new("张三", 30)
person = nil
collectgarbage("collect")  -- 输出 Person 对象被销毁:张三

面向对象的应用

示例 1:实现一个栈

lua
local Stack = {}
Stack.__index = Stack

function Stack:new()
  local obj = {}
  setmetatable(obj, self)
  obj.items = {}
  return obj
end

function Stack:push(item)
  table.insert(self.items, item)
end

function Stack:pop()
  return table.remove(self.items)
end

function Stack:size()
  return #self.items
end

function Stack:isEmpty()
  return #self.items == 0
end

-- 使用栈
local stack = Stack:new()
stack:push(1)
stack:push(2)
stack:push(3)
print(stack:pop())  -- 输出 3
print(stack:size())  -- 输出 2
print(stack:isEmpty())  -- 输出 false

示例 2:实现一个链表

lua
local Node = {}
Node.__index = Node

function Node:new(value)
  local obj = {}
  setmetatable(obj, self)
  obj.value = value
  obj.next = nil
  return obj
end

local LinkedList = {}
LinkedList.__index = LinkedList

function LinkedList:new()
  local obj = {}
  setmetatable(obj, self)
  obj.head = nil
  return obj
end

function LinkedList:add(value)
  local node = Node:new(value)
  if not self.head then
    self.head = node
  else
    local current = self.head
    while current.next do
      current = current.next
    end
    current.next = node
  end
end

function LinkedList:print()
  local current = self.head
  while current do
    print(current.value)
    current = current.next
  end
end

-- 使用链表
local list = LinkedList:new()
list:add(1)
list:add(2)
list:add(3)
list:print()  -- 输出 1, 2, 3

示例 3:实现一个图形类层次结构

lua
local Shape = {}
Shape.__index = Shape

function Shape:new(x, y)
  local obj = {}
  setmetatable(obj, self)
  obj.x = x
  obj.y = y
  return obj
end

function Shape:move(dx, dy)
  self.x = self.x + dx
  self.y = self.y + dy
end

function Shape:area()
  error("子类必须实现 area 方法")
end

local Circle = {}
Circle.__index = Circle
setmetatable(Circle, Shape)

function Circle:new(x, y, radius)
  local obj = Shape.new(self, x, y)
  obj.radius = radius
  return obj
end

function Circle:area()
  return math.pi * self.radius ^ 2
end

local Rectangle = {}
Rectangle.__index = Rectangle
setmetatable(Rectangle, Shape)

function Rectangle:new(x, y, width, height)
  local obj = Shape.new(self, x, y)
  obj.width = width
  obj.height = height
  return obj
end

function Rectangle:area()
  return self.width * self.height
end

-- 使用图形类
local circle = Circle:new(0, 0, 5)
print("圆的面积:" .. circle:area())

local rectangle = Rectangle:new(0, 0, 10, 5)
print("矩形的面积:" .. rectangle:area())

-- 多态
function printArea(shape)
  print("面积:" .. shape:area())
end

printArea(circle)
printArea(rectangle)

小结

本章节介绍了 Lua 中面向对象编程的基本概念和实现方法,包括类的定义、对象的创建和使用、继承、封装、多态,以及构造函数和析构函数的实现。掌握这些内容,对于编写复杂的 Lua 程序非常重要。