复习下lua的元表元方法,浅尝辄止。
目标是用lua实现以下C++例子的功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| class { public: std::string mName;
Anima(){} Anima(const std::string& str) : mName(str) {}
void SetName(const std::string& str); std::string GetName(); };
class Dog : public Anima { public: std::string mOwnerName;
Dog(){} Dog(const std::string& str) : Anima(str) {} void SetOwnerName(const std::string& str); std::string GetOwnerName() void PlayBall(); }
Dog dog(std::string("旺财")); dog.SetOwnerName(std::string("李狗蛋")); dog:PlayBall();
|
一、 元表、元方法介绍
lua中的变量是没有数据类型的,但是值具有类型:nil、number、boolean、string、function、thread、userdata和table。lua中的每个值都可以有元表(metatable)。元表定义了原始值在特性操作下的行为。可以在元表中设置特性的字段来改变作用域该值操作的某些行为。如对非数字类型做加法操作时,lua会检查该值的元表中的“add”函数,如果存在,那么则调用其完成加法操作,“add”函数就是元方法(metamethod)。
通过元表和元方法能实现C++的面向对象思想。
一个table默认不带元表,可以通过setmetatable设置元表。
1 2 3
| local t = {} setmetatable(t, t) print(t == getmetatable)
|
当我们想要通过继承的思想来访问基类的成员时,会这样写:
1 2 3 4
| local A = {} local B = {x = 10} setmetatable(A, B) print(A.x)
|
访问A.x时,A中没有x变量。便去A的元表B中查找,然而lua并不会直接在B中查找x,而是通过调用B的元方法index。如果没有index,那么返回nil。如果__index被赋值为一个表,那么就会去这个表中查询:
1 2 3 4 5
| local A = {} local B = {x = 10} B.__index = B setmetatable(A, B) print(A.x)
|
如果__index被赋值为一个函数,那么查找的时候就会返回函数的返回值。
1 2 3 4 5 6 7
| local A = {} local B = {x = 10} B.__index = function(t, key) print(key .. ' is not exist!') end setmetatable(A, B) print(A.x)
|
二、lua实现C++继承
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| local Anima = {mName = ''} Anima.__index = Anima
function Anima:new(str) local t = {}
setmetatable(t, self) if tostring(str) then self.mName = str end
return t end
function Anima:SetName(str) self.mName = str end
function Anima:GetName() return self.mName end
local Dog = {mOwnerName = ''} setmetatable(Dog, Anima) Dog.__index = Dog
function Dog:new(name) local t = Anima:new(name) setmetatable(t, self)
return t end
function Dog:SetOwnerName(name) self.mOwnerName = name end
function Dog:GetOwnerName() return self.mOwnerName end
function Dog:PlayBall() print(self.mName .. 'is playing with ' .. self.mOwnerName ) end
local dog = Dog:new('旺财') dog:SetOwnerName('李狗蛋') dog:PlayBall()
|