Lua面向对象编程
概述
虽然Lua不是一门纯面向对象的语言,但它提供了强大的元表(metatable)机制,使得我们可以实现完整的面向对象编程特性,包括类、对象、继承、多态和封装。
1. 面向对象基础概念
1.1 类和对象的基本实现
lua
-- 基本的类定义
local Person = {}
Person.__index = Person
-- 构造函数
function Person:new(name, age)
local obj = {
name = name or "Unknown",
age = age or 0
}
setmetatable(obj, self)
return obj
end
-- 实例方法
function Person:say_hello()
print("Hello, I'm " .. self.name .. " and I'm " .. self.age .. " years old.")
end
function Person:get_name()
return self.name
end
function Person:set_name(name)
self.name = name
end
function Person:get_age()
return self.age
end
function Person:set_age(age)
if age >= 0 then
self.age = age
else
error("年龄不能为负数")
end
end
-- 使用示例
local function basic_oop_example()
print("=== 基本面向对象示例 ===")
-- 创建对象
local person1 = Person:new("Alice", 30)
local person2 = Person:new("Bob", 25)
-- 调用方法
person1:say_hello()
person2:say_hello()
-- 修改属性
person1:set_name("Alice Smith")
person1:set_age(31)
print("修改后:")
person1:say_hello()
end
basic_oop_example()1.2 私有成员和封装
lua
-- 带有私有成员的类实现
local function create_bank_account_class()
local BankAccount = {}
BankAccount.__index = BankAccount
-- 私有数据存储
local private_data = setmetatable({}, {__mode = "k"})
function BankAccount:new(account_number, initial_balance)
local obj = {
account_number = account_number
}
-- 私有数据
private_data[obj] = {
balance = initial_balance or 0,
transaction_history = {}
}
setmetatable(obj, self)
return obj
end
-- 私有方法
local function add_transaction(self, type, amount)
local data = private_data[self]
table.insert(data.transaction_history, {
type = type,
amount = amount,
timestamp = os.time(),
balance_after = data.balance
})
end
-- 公有方法
function BankAccount:deposit(amount)
if amount <= 0 then
error("存款金额必须大于0")
end
local data = private_data[self]
data.balance = data.balance + amount
add_transaction(self, "deposit", amount)
return data.balance
end
function BankAccount:withdraw(amount)
if amount <= 0 then
error("取款金额必须大于0")
end
local data = private_data[self]
if amount > data.balance then
error("余额不足")
end
data.balance = data.balance - amount
add_transaction(self, "withdraw", amount)
return data.balance
end
function BankAccount:get_balance()
return private_data[self].balance
end
function BankAccount:get_transaction_history()
local data = private_data[self]
local history = {}
for _, transaction in ipairs(data.transaction_history) do
table.insert(history, {
type = transaction.type,
amount = transaction.amount,
timestamp = transaction.timestamp,
balance_after = transaction.balance_after
})
end
return history
end
function BankAccount:get_account_info()
return {
account_number = self.account_number,
balance = self:get_balance()
}
end
return BankAccount
end
-- 使用封装示例
local function encapsulation_example()
print("\n=== 封装示例 ===")
local BankAccount = create_bank_account_class()
local account = BankAccount:new("123456789", 1000)
print("初始余额:", account:get_balance())
-- 存款
account:deposit(500)
print("存款500后余额:", account:get_balance())
-- 取款
account:withdraw(200)
print("取款200后余额:", account:get_balance())
-- 查看交易历史
print("\n交易历史:")
local history = account:get_transaction_history()
for i, transaction in ipairs(history) do
print(string.format("%d. %s: %d, 余额: %d, 时间: %s",
i, transaction.type, transaction.amount,
transaction.balance_after, os.date("%Y-%m-%d %H:%M:%S", transaction.timestamp)))
end
-- 尝试访问私有数据(会失败)
print("\n尝试直接访问私有数据:")
print("account.balance:", account.balance) -- nil
end
encapsulation_example()2. 继承
2.1 单继承
lua
-- 基类:动物
local Animal = {}
Animal.__index = Animal
function Animal:new(name, species)
local obj = {
name = name or "Unknown",
species = species or "Unknown"
}
setmetatable(obj, self)
return obj
end
function Animal:speak()
print(self.name .. " makes a sound")
end
function Animal:get_info()
return string.format("%s is a %s", self.name, self.species)
end
function Animal:sleep()
print(self.name .. " is sleeping")
end
-- 派生类:狗
local Dog = setmetatable({}, Animal)
Dog.__index = Dog
function Dog:new(name, breed)
local obj = Animal.new(self, name, "Dog")
obj.breed = breed or "Mixed"
return obj
end
function Dog:speak() -- 重写父类方法
print(self.name .. " barks: Woof! Woof!")
end
function Dog:fetch() -- 新方法
print(self.name .. " fetches the ball")
end
function Dog:get_info() -- 重写并扩展父类方法
local base_info = Animal.get_info(self)
return base_info .. " (breed: " .. self.breed .. ")"
end
-- 派生类:猫
local Cat = setmetatable({}, Animal)
Cat.__index = Cat
function Cat:new(name, color)
local obj = Animal.new(self, name, "Cat")
obj.color = color or "Unknown"
return obj
end
function Cat:speak() -- 重写父类方法
print(self.name .. " meows: Meow! Meow!")
end
function Cat:climb() -- 新方法
print(self.name .. " climbs the tree")
end
function Cat:get_info() -- 重写并扩展父类方法
local base_info = Animal.get_info(self)
return base_info .. " (color: " .. self.color .. ")"
end
-- 继承示例
local function inheritance_example()
print("\n=== 继承示例 ===")
-- 创建动物对象
local animal = Animal:new("Generic Animal", "Unknown")
local dog = Dog:new("Buddy", "Golden Retriever")
local cat = Cat:new("Whiskers", "Orange")
-- 测试多态
local animals = {animal, dog, cat}
print("所有动物的信息:")
for _, a in ipairs(animals) do
print(" " .. a:get_info())
end
print("\n所有动物说话:")
for _, a in ipairs(animals) do
a:speak()
end
print("\n所有动物睡觉:")
for _, a in ipairs(animals) do
a:sleep()
end
print("\n特有行为:")
dog:fetch()
cat:climb()
end
inheritance_example()2.2 多重继承
lua
-- 多重继承的实现
local function create_multiple_inheritance()
-- 创建支持多重继承的函数
local function create_class(...)
local parents = {...}
local class = {}
-- 设置元表,支持多重继承查找
setmetatable(class, {
__index = function(t, k)
for _, parent in ipairs(parents) do
local v = parent[k]
if v then
return v
end
end
end
})
class.__index = class
class.__parents = parents
function class:new(...)
local obj = {}
setmetatable(obj, self)
-- 调用所有父类的初始化方法
for _, parent in ipairs(self.__parents or {}) do
if parent.init then
parent.init(obj, ...)
end
end
if self.init then
self:init(obj, ...)
end
return obj
end
return class
end
-- 定义混入类
local Flyable = {}
function Flyable:init()
self.can_fly = true
end
function Flyable:fly()
if self.can_fly then
print((self.name or "Something") .. " is flying")
else
print((self.name or "Something") .. " cannot fly")
end
end
local Swimmable = {}
function Swimmable:init()
self.can_swim = true
end
function Swimmable:swim()
if self.can_swim then
print((self.name or "Something") .. " is swimming")
else
print((self.name or "Something") .. " cannot swim")
end
end
-- 基类
local Bird = {}
function Bird:init(obj, name)
obj.name = name or "Bird"
obj.species = "Bird"
end
function Bird:speak()
print((self.name or "Bird") .. " chirps")
end
-- 多重继承:鸭子既能飞又能游泳
local Duck = create_class(Bird, Flyable, Swimmable)
function Duck:init(obj, name)
obj.name = name or "Duck"
obj.species = "Duck"
end
function Duck:speak()
print(self.name .. " quacks: Quack! Quack!")
end
-- 企鹅:是鸟但不能飞,只能游泳
local Penguin = create_class(Bird, Swimmable)
function Penguin:init(obj, name)
obj.name = name or "Penguin"
obj.species = "Penguin"
obj.can_fly = false -- 重写飞行能力
end
function Penguin:speak()
print(self.name .. " makes penguin sounds")
end
return Duck, Penguin
end
-- 多重继承示例
local function multiple_inheritance_example()
print("\n=== 多重继承示例 ===")
local Duck, Penguin = create_multiple_inheritance()
local duck = Duck:new("Donald")
local penguin = Penguin:new("Pingu")
print("鸭子的能力:")
duck:speak()
duck:fly()
duck:swim()
print("\n企鹅的能力:")
penguin:speak()
penguin:swim()
-- 企鹅没有fly方法,因为它没有继承Flyable
local success, err = pcall(function() penguin:fly() end)
if not success then
print("企鹅不能飞:", err)
end
end
multiple_inheritance_example()3. 多态
3.1 方法重写和动态分发
lua
-- 形状基类
local Shape = {}
Shape.__index = Shape
function Shape:new(x, y)
local obj = {
x = x or 0,
y = y or 0
}
setmetatable(obj, self)
return obj
end
function Shape:area()
error("子类必须实现area方法")
end
function Shape:perimeter()
error("子类必须实现perimeter方法")
end
function Shape:move(dx, dy)
self.x = self.x + dx
self.y = self.y + dy
end
function Shape:get_position()
return self.x, self.y
end
function Shape:describe()
return string.format("%s at (%.1f, %.1f)",
self.type or "Shape", self.x, self.y)
end
-- 矩形类
local Rectangle = setmetatable({}, Shape)
Rectangle.__index = Rectangle
function Rectangle:new(x, y, width, height)
local obj = Shape.new(self, x, y)
obj.width = width or 1
obj.height = height or 1
obj.type = "Rectangle"
return obj
end
function Rectangle:area()
return self.width * self.height
end
function Rectangle:perimeter()
return 2 * (self.width + self.height)
end
function Rectangle:describe()
local base_desc = Shape.describe(self)
return string.format("%s (%.1f x %.1f)", base_desc, self.width, self.height)
end
-- 圆形类
local Circle = setmetatable({}, Shape)
Circle.__index = Circle
function Circle:new(x, y, radius)
local obj = Shape.new(self, x, y)
obj.radius = radius or 1
obj.type = "Circle"
return obj
end
function Circle:area()
return math.pi * self.radius * self.radius
end
function Circle:perimeter()
return 2 * math.pi * self.radius
end
function Circle:describe()
local base_desc = Shape.describe(self)
return string.format("%s (radius: %.1f)", base_desc, self.radius)
end
-- 三角形类
local Triangle = setmetatable({}, Shape)
Triangle.__index = Triangle
function Triangle:new(x, y, a, b, c)
local obj = Shape.new(self, x, y)
obj.a = a or 1
obj.b = b or 1
obj.c = c or 1
obj.type = "Triangle"
return obj
end
function Triangle:area()
local s = (self.a + self.b + self.c) / 2
return math.sqrt(s * (s - self.a) * (s - self.b) * (s - self.c))
end
function Triangle:perimeter()
return self.a + self.b + self.c
end
function Triangle:describe()
local base_desc = Shape.describe(self)
return string.format("%s (sides: %.1f, %.1f, %.1f)",
base_desc, self.a, self.b, self.c)
end
-- 多态示例
local function polymorphism_example()
print("\n=== 多态示例 ===")
-- 创建不同类型的形状
local shapes = {
Rectangle:new(0, 0, 5, 3),
Circle:new(10, 10, 4),
Triangle:new(20, 20, 3, 4, 5)
}
-- 多态调用:同样的接口,不同的实现
print("所有形状的信息:")
for i, shape in ipairs(shapes) do
print(string.format("%d. %s", i, shape:describe()))
print(string.format(" 面积: %.2f, 周长: %.2f",
shape:area(), shape:perimeter()))
end
-- 移动所有形状
print("\n移动所有形状 (5, 5):")
for _, shape in ipairs(shapes) do
shape:move(5, 5)
local x, y = shape:get_position()
print(string.format("%s moved to (%.1f, %.1f)",
shape.type, x, y))
end
-- 计算总面积
local total_area = 0
for _, shape in ipairs(shapes) do
total_area = total_area + shape:area()
end
print(string.format("\n所有形状的总面积: %.2f", total_area))
end
polymorphism_example()3.2 接口和抽象类
lua
-- 接口的实现
local function create_interface(interface_name, methods)
local interface = {
__interface_name = interface_name,
__required_methods = methods
}
function interface:implements(class)
for _, method in ipairs(self.__required_methods) do
if type(class[method]) ~= "function" then
error(string.format("类必须实现接口 %s 的方法: %s",
self.__interface_name, method))
end
end
-- 标记类实现了该接口
class.__interfaces = class.__interfaces or {}
table.insert(class.__interfaces, self)
return class
end
return interface
end
-- 定义接口
local Drawable = create_interface("Drawable", {"draw", "get_bounds"})
local Serializable = create_interface("Serializable", {"serialize", "deserialize"})
-- 实现接口的类
local DrawableRectangle = setmetatable({}, Rectangle)
DrawableRectangle.__index = DrawableRectangle
function DrawableRectangle:new(x, y, width, height, color)
local obj = Rectangle.new(self, x, y, width, height)
obj.color = color or "black"
return obj
end
function DrawableRectangle:draw()
print(string.format("Drawing %s rectangle at (%.1f, %.1f) with size %.1fx%.1f",
self.color, self.x, self.y, self.width, self.height))
end
function DrawableRectangle:get_bounds()
return {
x = self.x,
y = self.y,
width = self.width,
height = self.height
}
end
function DrawableRectangle:serialize()
return {
type = "DrawableRectangle",
x = self.x,
y = self.y,
width = self.width,
height = self.height,
color = self.color
}
end
function DrawableRectangle:deserialize(data)
self.x = data.x
self.y = data.y
self.width = data.width
self.height = data.height
self.color = data.color
return self
end
-- 让类实现接口
Drawable:implements(DrawableRectangle)
Serializable:implements(DrawableRectangle)
-- 接口示例
local function interface_example()
print("\n=== 接口示例 ===")
local rect = DrawableRectangle:new(10, 20, 100, 50, "red")
-- 使用接口方法
rect:draw()
local bounds = rect:get_bounds()
print("边界:", bounds.x, bounds.y, bounds.width, bounds.height)
-- 序列化和反序列化
local data = rect:serialize()
print("序列化数据:", data.type, data.color)
local new_rect = DrawableRectangle:new()
new_rect:deserialize(data)
new_rect:draw()
-- 检查接口实现
print("实现的接口:")
for _, interface in ipairs(DrawableRectangle.__interfaces or {}) do
print(" " .. interface.__interface_name)
end
end
interface_example()4. 高级面向对象特性
4.1 属性访问器
lua
-- 带有属性访问器的类
local function create_property_class()
local Person = {}
Person.__index = Person
-- 私有数据存储
local private_data = setmetatable({}, {__mode = "k"})
function Person:new(name, age)
local obj = {}
-- 初始化私有数据
private_data[obj] = {
name = name or "",
age = age or 0,
email = ""
}
-- 设置元表以支持属性访问
setmetatable(obj, {
__index = function(t, k)
-- 首先检查是否是方法
if Person[k] then
return Person[k]
end
-- 然后检查是否是属性
local data = private_data[t]
if data and data[k] ~= nil then
return data[k]
end
-- 检查是否有getter方法
local getter = Person["get_" .. k]
if getter then
return getter(t)
end
return nil
end,
__newindex = function(t, k, v)
-- 检查是否有setter方法
local setter = Person["set_" .. k]
if setter then
setter(t, v)
return
end
-- 直接设置私有数据
local data = private_data[t]
if data then
data[k] = v
end
end
})
return obj
end
-- 属性访问器
function Person:get_name()
return private_data[self].name
end
function Person:set_name(name)
if type(name) ~= "string" or #name == 0 then
error("姓名必须是非空字符串")
end
private_data[self].name = name
end
function Person:get_age()
return private_data[self].age
end
function Person:set_age(age)
if type(age) ~= "number" or age < 0 or age > 150 then
error("年龄必须是0-150之间的数字")
end
private_data[self].age = age
end
function Person:get_email()
return private_data[self].email
end
function Person:set_email(email)
if not string.match(email, "^[%w%.%-_]+@[%w%.%-_]+%.%w+$") then
error("邮箱格式不正确")
end
private_data[self].email = email
end
-- 计算属性
function Person:get_full_info()
local data = private_data[self]
return string.format("%s (%d years old) - %s",
data.name, data.age, data.email)
end
function Person:get_is_adult()
return private_data[self].age >= 18
end
return Person
end
-- 属性访问器示例
local function property_example()
print("\n=== 属性访问器示例 ===")
local Person = create_property_class()
local person = Person:new("Alice", 25)
-- 使用属性访问器
print("姓名:", person.name)
print("年龄:", person.age)
-- 设置属性
person.name = "Alice Smith"
person.age = 30
person.email = "alice@example.com"
print("更新后信息:", person.full_info)
print("是否成年:", person.is_adult)
-- 测试验证
local success, err = pcall(function()
person.age = -5
end)
print("设置无效年龄:", success and "成功" or err)
success, err = pcall(function()
person.email = "invalid-email"
end)
print("设置无效邮箱:", success and "成功" or err)
end
property_example()4.2 操作符重载
lua
-- 向量类,演示操作符重载
local Vector = {}
Vector.__index = Vector
function Vector:new(x, y)
local obj = {
x = x or 0,
y = y or 0
}
setmetatable(obj, self)
return obj
end
-- 重载加法操作符
function Vector:__add(other)
return Vector:new(self.x + other.x, self.y + other.y)
end
-- 重载减法操作符
function Vector:__sub(other)
return Vector:new(self.x - other.x, self.y - other.y)
end
-- 重载乘法操作符(标量乘法)
function Vector:__mul(scalar)
if type(scalar) == "number" then
return Vector:new(self.x * scalar, self.y * scalar)
elseif type(self) == "number" then
return Vector:new(scalar.x * self, scalar.y * self)
else
error("向量只能与数字相乘")
end
end
-- 重载除法操作符
function Vector:__div(scalar)
if type(scalar) ~= "number" or scalar == 0 then
error("向量只能被非零数字除")
end
return Vector:new(self.x / scalar, self.y / scalar)
end
-- 重载一元负号操作符
function Vector:__unm()
return Vector:new(-self.x, -self.y)
end
-- 重载等于操作符
function Vector:__eq(other)
return self.x == other.x and self.y == other.y
end
-- 重载小于操作符(按长度比较)
function Vector:__lt(other)
return self:length() < other:length()
end
-- 重载小于等于操作符
function Vector:__le(other)
return self:length() <= other:length()
end
-- 重载字符串转换
function Vector:__tostring()
return string.format("Vector(%.2f, %.2f)", self.x, self.y)
end
-- 重载长度操作符
function Vector:__len()
return math.floor(self:length())
end
-- 重载索引访问
function Vector:__index(key)
if key == 1 or key == "x" then
return rawget(self, "x")
elseif key == 2 or key == "y" then
return rawget(self, "y")
else
return Vector[key]
end
end
-- 重载索引设置
function Vector:__newindex(key, value)
if key == 1 or key == "x" then
rawset(self, "x", value)
elseif key == 2 or key == "y" then
rawset(self, "y", value)
else
rawset(self, key, value)
end
end
-- 实例方法
function Vector:length()
return math.sqrt(self.x * self.x + self.y * self.y)
end
function Vector:normalize()
local len = self:length()
if len == 0 then
return Vector:new(0, 0)
end
return Vector:new(self.x / len, self.y / len)
end
function Vector:dot(other)
return self.x * other.x + self.y * other.y
end
-- 操作符重载示例
local function operator_overloading_example()
print("\n=== 操作符重载示例 ===")
local v1 = Vector:new(3, 4)
local v2 = Vector:new(1, 2)
print("v1 =", v1)
print("v2 =", v2)
-- 算术操作
print("v1 + v2 =", v1 + v2)
print("v1 - v2 =", v1 - v2)
print("v1 * 2 =", v1 * 2)
print("v1 / 2 =", v1 / 2)
print("-v1 =", -v1)
-- 比较操作
print("v1 == v2:", v1 == v2)
print("v1 < v2:", v1 < v2)
print("v1 <= v2:", v1 <= v2)
-- 长度操作
print("length of v1:", #v1)
print("actual length of v1:", v1:length())
-- 索引访问
print("v1[1] =", v1[1])
print("v1[2] =", v1[2])
print("v1.x =", v1.x)
print("v1.y =", v1.y)
-- 修改值
v1[1] = 5
v1.y = 6
print("修改后 v1 =", v1)
-- 向量运算
print("v1 · v2 =", v1:dot(v2))
print("normalized v1 =", v1:normalize())
end
operator_overloading_example()4.3 类装饰器和混入
lua
-- 装饰器系统
local function create_decorator_system()
local decorators = {}
-- 日志装饰器
decorators.logged = function(class)
local original_new = class.new
class.new = function(self, ...)
local obj = original_new(self, ...)
print("创建了 " .. (class.__name or "Unknown") .. " 的实例")
return obj
end
-- 装饰所有方法
for name, method in pairs(class) do
if type(method) == "function" and name ~= "new" and not string.match(name, "^__") then
class[name] = function(self, ...)
print("调用方法: " .. (class.__name or "Unknown") .. ":" .. name)
return method(self, ...)
end
end
end
return class
end
-- 单例装饰器
decorators.singleton = function(class)
local instance = nil
local original_new = class.new
class.new = function(self, ...)
if not instance then
instance = original_new(self, ...)
print("创建单例实例: " .. (class.__name or "Unknown"))
else
print("返回现有单例实例: " .. (class.__name or "Unknown"))
end
return instance
end
return class
end
-- 缓存装饰器
decorators.cached = function(class)
local cache = {}
-- 装饰指定的方法
local function cache_method(method_name)
local original_method = class[method_name]
if original_method then
class[method_name] = function(self, ...)
local key = table.concat({...}, ",")
local cache_key = method_name .. ":" .. key
if cache[cache_key] then
print("缓存命中: " .. method_name)
return cache[cache_key]
end
local result = original_method(self, ...)
cache[cache_key] = result
print("缓存存储: " .. method_name)
return result
end
end
end
-- 为类添加缓存方法的功能
class.cache_method = cache_method
return class
end
return decorators
end
-- 混入系统
local function create_mixin_system()
local mixins = {}
-- 时间戳混入
mixins.Timestamped = {
init_timestamp = function(self)
self.created_at = os.time()
self.updated_at = os.time()
end,
touch = function(self)
self.updated_at = os.time()
end,
get_age = function(self)
return os.time() - self.created_at
end
}
-- 可观察混入
mixins.Observable = {
init_observable = function(self)
self.observers = {}
end,
add_observer = function(self, observer)
table.insert(self.observers, observer)
end,
remove_observer = function(self, observer)
for i, obs in ipairs(self.observers) do
if obs == observer then
table.remove(self.observers, i)
break
end
end
end,
notify_observers = function(self, event, ...)
for _, observer in ipairs(self.observers) do
if observer[event] then
observer[event](observer, self, ...)
end
end
end
}
-- 混入应用函数
local function apply_mixin(class, mixin)
for name, method in pairs(mixin) do
if not class[name] then
class[name] = method
end
end
return class
end
return mixins, apply_mixin
end
-- 装饰器和混入示例
local function decorator_mixin_example()
print("\n=== 装饰器和混入示例 ===")
local decorators = create_decorator_system()
local mixins, apply_mixin = create_mixin_system()
-- 定义一个简单的类
local Calculator = {}
Calculator.__index = Calculator
Calculator.__name = "Calculator"
function Calculator:new()
local obj = {}
setmetatable(obj, self)
-- 初始化混入
if self.init_timestamp then
self:init_timestamp(obj)
end
if self.init_observable then
self:init_observable(obj)
end
return obj
end
function Calculator:add(a, b)
local result = a + b
if self.notify_observers then
self:notify_observers("calculation_done", "add", a, b, result)
end
return result
end
function Calculator:multiply(a, b)
local result = a * b
if self.notify_observers then
self:notify_observers("calculation_done", "multiply", a, b, result)
end
return result
end
function Calculator:fibonacci(n)
if n <= 1 then return n end
return self:fibonacci(n - 1) + self:fibonacci(n - 2)
end
-- 应用混入
apply_mixin(Calculator, mixins.Timestamped)
apply_mixin(Calculator, mixins.Observable)
-- 应用装饰器
Calculator = decorators.cached(Calculator)
Calculator = decorators.logged(Calculator)
-- 缓存斐波那契方法
Calculator:cache_method("fibonacci")
-- 创建观察者
local observer = {
calculation_done = function(self, calculator, operation, a, b, result)
print(string.format("观察者: %s(%d, %d) = %d", operation, a, b, result))
end
}
-- 使用增强的类
local calc = Calculator:new()
calc:add_observer(observer)
print("计算器年龄:", calc:get_age(), "秒")
calc:add(5, 3)
calc:multiply(4, 6)
-- 测试缓存
print("第一次计算 fibonacci(10):")
print("结果:", calc:fibonacci(10))
print("第二次计算 fibonacci(10):")
print("结果:", calc:fibonacci(10))
end
decorator_mixin_example()5. 设计模式实现
5.1 观察者模式
lua
-- 观察者模式的完整实现
local function create_observer_pattern()
-- 主题(被观察者)
local Subject = {}
Subject.__index = Subject
function Subject:new()
local obj = {
observers = {},
state = nil
}
setmetatable(obj, self)
return obj
end
function Subject:attach(observer)
table.insert(self.observers, observer)
end
function Subject:detach(observer)
for i, obs in ipairs(self.observers) do
if obs == observer then
table.remove(self.observers, i)
break
end
end
end
function Subject:notify()
for _, observer in ipairs(self.observers) do
observer:update(self)
end
end
function Subject:set_state(state)
self.state = state
self:notify()
end
function Subject:get_state()
return self.state
end
-- 具体观察者
local Observer = {}
Observer.__index = Observer
function Observer:new(name)
local obj = {
name = name or "Observer"
}
setmetatable(obj, self)
return obj
end
function Observer:update(subject)
print(string.format("%s 收到通知: 状态变为 %s",
self.name, tostring(subject:get_state())))
end
return Subject, Observer
end
-- 观察者模式示例
local function observer_pattern_example()
print("\n=== 观察者模式示例 ===")
local Subject, Observer = create_observer_pattern()
local subject = Subject:new()
local observer1 = Observer:new("观察者1")
local observer2 = Observer:new("观察者2")
local observer3 = Observer:new("观察者3")
-- 注册观察者
subject:attach(observer1)
subject:attach(observer2)
subject:attach(observer3)
-- 改变状态
print("设置状态为 'Active':")
subject:set_state("Active")
print("\n移除观察者2后,设置状态为 'Inactive':")
subject:detach(observer2)
subject:set_state("Inactive")
end
observer_pattern_example()5.2 策略模式
lua
-- 策略模式实现
local function create_strategy_pattern()
-- 策略接口
local Strategy = {}
-- 具体策略:冒泡排序
local BubbleSort = {}
BubbleSort.__index = BubbleSort
function BubbleSort:new()
return setmetatable({name = "冒泡排序"}, self)
end
function BubbleSort:sort(array)
local arr = {}
for i, v in ipairs(array) do
arr[i] = v
end
local n = #arr
for i = 1, n - 1 do
for j = 1, n - i do
if arr[j] > arr[j + 1] then
arr[j], arr[j + 1] = arr[j + 1], arr[j]
end
end
end
return arr
end
-- 具体策略:快速排序
local QuickSort = {}
QuickSort.__index = QuickSort
function QuickSort:new()
return setmetatable({name = "快速排序"}, self)
end
function QuickSort:sort(array)
local arr = {}
for i, v in ipairs(array) do
arr[i] = v
end
local function quicksort(arr, low, high)
if low < high then
local pi = partition(arr, low, high)
quicksort(arr, low, pi - 1)
quicksort(arr, pi + 1, high)
end
end
local function partition(arr, low, high)
local pivot = arr[high]
local i = low - 1
for j = low, high - 1 do
if arr[j] <= pivot then
i = i + 1
arr[i], arr[j] = arr[j], arr[i]
end
end
arr[i + 1], arr[high] = arr[high], arr[i + 1]
return i + 1
end
quicksort(arr, 1, #arr)
return arr
end
-- 上下文类
local SortContext = {}
SortContext.__index = SortContext
function SortContext:new(strategy)
local obj = {
strategy = strategy
}
setmetatable(obj, self)
return obj
end
function SortContext:set_strategy(strategy)
self.strategy = strategy
end
function SortContext:execute_sort(array)
if not self.strategy then
error("未设置排序策略")
end
print("使用 " .. self.strategy.name .. " 进行排序")
return self.strategy:sort(array)
end
return SortContext, BubbleSort, QuickSort
end
-- 策略模式示例
local function strategy_pattern_example()
print("\n=== 策略模式示例 ===")
local SortContext, BubbleSort, QuickSort = create_strategy_pattern()
local data = {64, 34, 25, 12, 22, 11, 90}
print("原始数据:", table.concat(data, ", "))
local context = SortContext:new()
-- 使用冒泡排序
context:set_strategy(BubbleSort:new())
local result1 = context:execute_sort(data)
print("排序结果:", table.concat(result1, ", "))
-- 使用快速排序
context:set_strategy(QuickSort:new())
local result2 = context:execute_sort(data)
print("排序结果:", table.concat(result2, ", "))
end
strategy_pattern_example()6. 总结
Lua的面向对象编程虽然不是内置特性,但通过元表机制可以实现完整的OOP功能:
核心概念
- 类和对象 - 使用表和元表实现
- 封装 - 通过闭包和私有数据实现
- 继承 - 通过元表链实现单继承和多重继承
- 多态 - 通过方法重写和动态分发实现
高级特性
- 属性访问器 - 通过__index和__newindex元方法实现
- 操作符重载 - 通过元方法实现各种操作符
- 装饰器和混入 - 增强类的功能
- 设计模式 - 实现各种经典设计模式
最佳实践
- 使用局部变量存储私有数据
- 合理使用元表避免性能问题
- 保持接口简洁清晰
- 适当使用设计模式提高代码质量
Lua的OOP系统虽然需要手动实现,但提供了极大的灵活性,可以根据具体需求定制最适合的面向对象方案。