Lua 本身不是一个面向对象的语言,但它提供了强大而灵活的机制来实现面向对象编程(OOP)的概念。本章将探讨如何在 Lua 中实现类、对象、继承和多态等 OOP 特性。
6.1 使用表实现类
在 Lua 中,我们使用表和函数来模拟类和对象。
基本类的实现
local Dog = {}
Dog.__index = Dog
function Dog.new(name)
local self = setmetatable({}, Dog)
self.name = name
return self
end
function 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)
end
myDog:eat("kibble") -- 输出: Buddy is eating kibble
冒号语法 :
自动将调用对象作为第一个参数(self)传递给方法。
6.3 继承的实现
Lua 使用元表来实现继承。
local Animal = {}
Animal.__index = Animal
function Animal.new(name)
local self = setmetatable({}, Animal)
self.name = name
return self
end
function Animal:speak()
print(self.name .. " makes a sound")
end
-- Cat 继承自 Animal
local Cat = setmetatable({}, {__index = Animal})
Cat.__index = Cat
function Cat.new(name)
local self = setmetatable(Animal.new(name), Cat)
return self
end
function Cat:speak()
print(self.name .. " meows")
end
-- 使用
local myCat = Cat.new("Whiskers")
myCat:speak() -- 输出: Whiskers meows
6.4 多态
多态允许不同类的对象对同一消息做出响应。
local function makeSound(animal)
animal:speak()
end
local 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 = name
function self:getAge()
return age
end
function self:haveBirthday()
age = age + 1
end
return self
end
local myDog = Dog.new("Spot")
myDog:haveBirthday()
print(myDog:getAge()) -- 输出: 1
print(myDog.age) -- 输出: nil
6.6 元方法和运算符重载
元方法允许自定义表的行为,包括运算符重载。
local Vector = {}
Vector.__index = Vector
function Vector.new(x, y)
return setmetatable({x = x, y = y}, Vector)
end
function Vector:__add(other)
return Vector.new(self.x + other.x, self.y + other.y)
end
function Vector:__tostring()
return "(" .. self.x .. ", " .. self.y .. ")"
end
local v1 = Vector.new(1, 2)
local v2 = Vector.new(3, 4)
local v3 = v1 + v2
print(v3) -- 输出: (4, 6)
6.7 面向对象设计模式
单例模式
local Singleton = {}
function Singleton.getInstance()
if not Singleton.instance then
Singleton.instance = {
data = 0,
incrementData = function(self)
self.data = self.data + 1
end
}
end
return Singleton.instance
end
local s1 = Singleton.getInstance()
local s2 = Singleton.getInstance()
s1:incrementData()
print(s2.data) -- 输出: 1
工厂模式
local ShapeFactory = {}
function ShapeFactory.createShape(shapeType)
if shapeType == "circle" then
return {
draw = function() print("Drawing a circle") end
}
elseif shapeType == "square" then
return {
draw = function() print("Drawing a square") end
}
else
error("Unsupported shape type")
end
end
local circle = ShapeFactory.createShape("circle")
circle.draw() -- 输出: Drawing a circle
6.8 实践项目:简单的图形库
让我们创建一个简单的图形库来演示面向对象编程的概念。
-- Shape 基类
local Shape = {}
Shape.__index = Shape
function Shape.new()
return setmetatable({}, Shape)
end
function Shape:draw()
error("Draw method must be implemented by subclasses")
end
-- Circle 类
local Circle = setmetatable({}, {__index = Shape})
Circle.__index = Circle
function Circle.new(radius)
local self = setmetatable(Shape.new(), Circle)
self.radius = radius
return self
end
function Circle:draw()
print("Drawing a circle with radius " .. self.radius)
end
-- Rectangle 类
local Rectangle = setmetatable({}, {__index = Shape})
Rectangle.__index = Rectangle
function Rectangle.new(width, height)
local self = setmetatable(Shape.new(), Rectangle)
self.width = width
self.height = height
return self
end
function 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) do
shape:draw()
end
练习
- 扩展图形库,添加更多形状(如三角形)和其他方法(如计算面积)。
- 实现一个简单的动物层次结构,包括不同种类的动物和它们的特定行为。
- 创建一个基本的银行账户系统,支持不同类型的账户(如储蓄账户、支票账户)和常见的银行操作。
通过本章的学习,你应该能够在 Lua 中实现面向对象编程的核心概念,并应用这些概念来设计和构建更复杂的系统。记住,虽然 Lua 不是一个传统的面向对象语言,但它提供了足够的灵活性来实现强大的面向对象设计。