Lua 面向对象
在 Lua 中并没有类的概念, 但是可以通过 table、function 与元表可以模拟和构造具有类功能的结构;
对象的创建
Lua 中通过 table 和 function 可以创造简单的 Lua 对象; table 为 Lua 对象赋予属性, function 给对象赋予行为;
对象创建示例如下所示:
lua
-- object_create_test.lua
-- 创建名为 animal 的对象
local animal = {
name = "Tom",
age = 5
};
-- 为对象添加方法
-- animal.bark = function(voice)
-- print(animal.name .. "在" .. voice .. "叫");
-- end
-- 解决 标红 行的问题: 方式一
-- animal.bark = function(self, voice)
-- print(self.name .. "在" .. voice .. "叫");
-- end
-- 解决 标红 行的问题:方式二
function animal:bark(voice) -- 这种函数定义方式,自带 self
print(self.name .. "在" .. voice .. "叫");
end
-- 直接调用对象的方法
-- animal.bark("喵喵");
animal.bark(animal, "喵喵");
animal:bark("喵喵"); -- 这种函数调用方式 自带 self
local animal_2 = animal; -- 两个animal指向的是同一个对象
animal = nil; -- 消除 animal 这个指针
-- 此时会出现异常,因为在 bark 方法中使用了已经为空的 animal 见黄色行注释处
-- animal_2.bark("旺旺");
animal_2.bark(animal_2, "旺旺");
animal_2:bark("旺旺");
最终执行结果如下:
类的创建
NOTE
类是属性和行为的抽象, 是对象创建的模板, 对象是具体的属性以及行为; 请注意两者的区别, 可参考: java中类与对象的关系与区别
Lua 中使用 table、function 与元表定义类; 表作为基础类, 使用一个 function 作为创建该基类示例对象的 new() 方法;
使用 new() 方法创建一个空表, 再给空表指定一个元表, 该元表重写
__index
方法, 且将基础表指定为重写的__index
方法;因为 new() 的是空表, 所以用户访问的所有 key 都从基表中获取;
具体示例如下所示:
lua
-- class_create_test.lua
-- 创建一个类
local Animal = {
name = "no_name",
age = 0
};
-- 创建无参构造器
function Animal:new() -- 隐藏参数 self
-- 创建一个空表
local a = {};
-- 绑定匿名元表 并重写元方法
setmetatable(a, {
__index = self, -- 新表中没有的 key 会在原始表中查找
});
return a; -- 返回新表
end
-- 创建有参构造器 - 参数是 table 类型
-- function Animal:new(obj)
-- local a = {};
-- if type(obj) == "table" then
-- a = obj;
-- end
-- setmetatable(a, { __index = self });
-- return a;
-- end
-- 尝试创建对象
local animal_1 = Animal:new();
local animal_2 = Animal:new();
-- 验证是否为两个不同的对象
print(animal_1);
print(animal_2);
-- 进行对象属性赋值
animal_1.name = "Tom";
animal_1.age = 8;
animal_1.type = "猫";
运行结果如下:
类的继承
主要是通过模拟来实现类的继承, 显得非常牵强;
示例如下所示:
lua
-- class_extend_test.lua
-- 先创建一个 Animal 类
local Animal = {
name = "no_name",
age = 0
};
-- 创建有参构造器
function Animal:new(obj) -- 隐藏参数 self
-- 创建一个空表
local a = obj or {};
-- 绑定匿名元表 并重写元方法
setmetatable(a, {
__index = self, -- 新表中没有的 key 会在原始表中查找
});
return a; -- 返回新表
end
-- 创建 Animal 的子类
local Cat = Animal:new({ type = "波斯猫" });
-- 子类属性
Cat.eyes = "蓝色";
-- 创建子类 实例
local tomcat = Cat:new();
tomcat.name = "Tom";
print(tomcat.name);
print(tomcat.eyes);
print(tomcat.type);
执行结果如下: