Lua 本身不是一个面向对象的语言,但它提供了强大而灵活的机制来实现面向对象编程(OOP)的概念。本章将探讨如何在 Lua 中实现类、对象、继承和多态等 OOP 特性。
6.1 使用表实现类
在 Lua 中,我们使用表和函数来模拟类和对象。
基本类的实现
local Dog = {}Dog.__index = Dogfunction Dog.new(name)local self = setmetatable({}, Dog)self.name = namereturn selfendfunction Dog:bark()print(self.name .. " says: Woof!")end-- 使用类local myDog = Dog.new("Buddy")myDog:bark() -- 输出: Buddy says: Woof!
6.2 方法和self参数
在 Lua 中,self 是一个隐含的参数,代表调用方法的对象实例。
使用冒号语法
function Dog:eat(food)print(self.name .. " is eating " .. food)endmyDog:eat("kibble") -- 输出: Buddy is eating kibble
冒号语法 : 自动将调用对象作为第一个参数(self)传递给方法。
6.3 继承的实现
Lua 使用元表来实现继承。
local Animal = {}Animal.__index = Animalfunction Animal.new(name)local self = setmetatable({}, Animal)self.name = namereturn selfendfunction Animal:speak()print(self.name .. " makes a sound")end-- Cat 继承自 Animallocal Cat = setmetatable({}, {__index = Animal})Cat.__index = Catfunction Cat.new(name)local self = setmetatable(Animal.new(name), Cat)return selfendfunction Cat:speak()print(self.name .. " meows")end-- 使用local myCat = Cat.new("Whiskers")myCat:speak() -- 输出: Whiskers meows
6.4 多态
多态允许不同类的对象对同一消息做出响应。
local function makeSound(animal)animal:speak()endlocal myDog = Dog.new("Rex")local myCat = Cat.new("Fluffy")makeSound(myDog) -- 输出: Rex says: Woof!makeSound(myCat) -- 输出: Fluffy meows
6.5 私有成员的模拟
Lua 没有内置的私有成员机制,但我们可以使用闭包来模拟。
function Dog.new(name)local age = 0 -- 私有变量local self = setmetatable({}, Dog)self.name = namefunction self:getAge()return ageendfunction self:haveBirthday()age = age + 1endreturn selfendlocal myDog = Dog.new("Spot")myDog:haveBirthday()print(myDog:getAge()) -- 输出: 1print(myDog.age) -- 输出: nil
6.6 元方法和运算符重载
元方法允许自定义表的行为,包括运算符重载。
local Vector = {}Vector.__index = Vectorfunction Vector.new(x, y)return setmetatable({x = x, y = y}, Vector)endfunction Vector:__add(other)return Vector.new(self.x + other.x, self.y + other.y)endfunction Vector:__tostring()return "(" .. self.x .. ", " .. self.y .. ")"endlocal v1 = Vector.new(1, 2)local v2 = Vector.new(3, 4)local v3 = v1 + v2print(v3) -- 输出: (4, 6)
6.7 面向对象设计模式
单例模式
local Singleton = {}function Singleton.getInstance()if not Singleton.instance thenSingleton.instance = {data = 0,incrementData = function(self)self.data = self.data + 1end}endreturn Singleton.instanceendlocal s1 = Singleton.getInstance()local s2 = Singleton.getInstance()s1:incrementData()print(s2.data) -- 输出: 1
工厂模式
local ShapeFactory = {}function ShapeFactory.createShape(shapeType)if shapeType == "circle" thenreturn {draw = function() print("Drawing a circle") end}elseif shapeType == "square" thenreturn {draw = function() print("Drawing a square") end}elseerror("Unsupported shape type")endendlocal circle = ShapeFactory.createShape("circle")circle.draw() -- 输出: Drawing a circle
6.8 实践项目:简单的图形库
让我们创建一个简单的图形库来演示面向对象编程的概念。
-- Shape 基类local Shape = {}Shape.__index = Shapefunction Shape.new()return setmetatable({}, Shape)endfunction Shape:draw()error("Draw method must be implemented by subclasses")end-- Circle 类local Circle = setmetatable({}, {__index = Shape})Circle.__index = Circlefunction Circle.new(radius)local self = setmetatable(Shape.new(), Circle)self.radius = radiusreturn selfendfunction Circle:draw()print("Drawing a circle with radius " .. self.radius)end-- Rectangle 类local Rectangle = setmetatable({}, {__index = Shape})Rectangle.__index = Rectanglefunction Rectangle.new(width, height)local self = setmetatable(Shape.new(), Rectangle)self.width = widthself.height = heightreturn selfendfunction Rectangle:draw()print("Drawing a rectangle " .. self.width .. "x" .. self.height)end-- 使用图形库local shapes = {Circle.new(5),Rectangle.new(4, 6),Circle.new(3)}for _, shape in ipairs(shapes) doshape:draw()end
练习
- 扩展图形库,添加更多形状(如三角形)和其他方法(如计算面积)。
- 实现一个简单的动物层次结构,包括不同种类的动物和它们的特定行为。
- 创建一个基本的银行账户系统,支持不同类型的账户(如储蓄账户、支票账户)和常见的银行操作。
通过本章的学习,你应该能够在 Lua 中实现面向对象编程的核心概念,并应用这些概念来设计和构建更复杂的系统。记住,虽然 Lua 不是一个传统的面向对象语言,但它提供了足够的灵活性来实现强大的面向对象设计。
