模块与包

       本节将全面讲解Lua模块化开发、包管理机制以及在Android平台下的特殊应用场景和优化技巧。

1. 模块基础

1.1 模块定义

-- 文件: mymodule.lua
local M = {}  -- 模块表

-- 公有函数
function M.sayHello(name)
    print("Hello, "..(name or "Lua"))
end

-- 私有函数
local function privateFunc()
    print("内部实现")
end

return M  -- 返回模块表

1.2 模块加载

-- 加载模块
local mymodule = require("mymodule")

-- 使用模块函数
mymodule.sayHello("Android")

-- 自定义加载路径
package.path = package.path .. ";/sdcard/lua/?.lua"

注意: Android中建议将模块放在assets目录,通过修改package.path加载

2. 模块加载机制

2.1 require工作原理

-- 1. 检查package.loaded缓存
-- 2. 按package.path路径查找文件
-- 3. 按package.cpath查找C模块
-- 4. 调用loader加载模块
-- 5. 结果存入package.loaded

2.2 自定义加载器

-- 从Android assets加载
table.insert(package.loaders, 2, function(modname)
    local assetFile = "lua/"..modname:gsub("%.", "/")..".lua"
    local content = android.loadAsset(assetFile)
    if content then
        return load(content, "="..modname)
    end
end)

-- 使用示例
require("com.example.mymodule")

3. 包管理

3.1 LuaRocks包管理

# 安装LuaRocks
luarocks install luasocket

-- 代码中使用
local socket = require("socket")

3.2 Android集成方案

-- 预编译库放入assets
local function loadLibrary(name)
    local soPath = android.extractAsset("lib"..name..".so")
    package.cpath = package.cpath .. ";" .. soPath.."/?.so"
    return require(name)
end

-- 加载C模块
local mylib = loadLibrary("mylib")

4. 面向对象模块

4.1 类定义模块

-- 文件: class.lua
local Class = {}

function Class:new(o)
    o = o or {}
    setmetatable(o, self)
    self.__index = self
    return o
end

return Class

-- 使用示例
local Rectangle = require("class")
function Rectangle:area()
    return self.width * self.height
end

4.2 继承实现

-- 继承基类
local Square = require("class"):new()

function Square:new(side)
    local o = Rectangle:new{width=side, height=side}
    setmetatable(o, self)
    self.__index = self
    return o
end

5. Android开发实践

5.1 模块热更新

-- 热加载模块
function hotReload(moduleName)
    package.loaded[moduleName] = nil
    return require(moduleName)
end

-- 从网络更新模块
local newModule = downloadModule("mymodule.lua")
local func, err = load(newModule, "mymodule")
if func then
    package.loaded["mymodule"] = func()
end

5.2 模块化架构

-- 业务模块划分
local App = {
    network = require("lib.network"),
    ui = require("ui.main"),
    utils = require("utils")
}

-- 启动应用
function App:run()
    self.ui.init()
    self.network.start()
end

return App

6. 性能优化

6.1 模块缓存

-- 预加载常用模块
local function preloadModules()
    require("json")
    require("socket")
    require("ui.templates")
end

-- 减少运行时加载开销

6.2 延迟加载

-- 按需加载模块
local LazyLoader = {}

function LazyLoader.load(moduleName)
    return setmetatable({}, {
        __index = function(_, key)
            local mod = require(moduleName)
            LazyLoader[moduleName] = mod
            return mod[key]
        end
    })
end

-- 使用示例
local heavyModule = LazyLoader.load("heavy.module")

7. 调试与测试

7.1 模块依赖分析

-- 打印模块依赖树
function printDeps(modname, level)
    level = level or 0
    local indent = string.rep("  ", level)
    print(indent..modname)
    
    if package.loaded[modname] then
        local info = debug.getinfo(package.loaders[1](modname))
        for line in io.lines(info.source:sub(2)) do
            local dep = line:match("require%(\"([%w.]+)\"%)")
            if dep then printDeps(dep, level + 1) end
        end
    end
end

7.2 单元测试

-- 测试模块示例
local test = require("test")

function test.mymodule()
    local mymodule = require("mymodule")
    assert(mymodule.add(1,2) == 3)
end

return test