Skip to content

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功能:

核心概念

  1. 类和对象 - 使用表和元表实现
  2. 封装 - 通过闭包和私有数据实现
  3. 继承 - 通过元表链实现单继承和多重继承
  4. 多态 - 通过方法重写和动态分发实现

高级特性

  1. 属性访问器 - 通过__index和__newindex元方法实现
  2. 操作符重载 - 通过元方法实现各种操作符
  3. 装饰器和混入 - 增强类的功能
  4. 设计模式 - 实现各种经典设计模式

最佳实践

  1. 使用局部变量存储私有数据
  2. 合理使用元表避免性能问题
  3. 保持接口简洁清晰
  4. 适当使用设计模式提高代码质量

Lua的OOP系统虽然需要手动实现,但提供了极大的灵活性,可以根据具体需求定制最适合的面向对象方案。

基于 MIT 许可发布