浅谈Lua面向对象的实现

来源:互联网 发布:深圳平湖淘宝客服招聘 编辑:程序博客网 时间:2024/04/30 10:02
一:lua的类实现
有时候有些lua对象(其实就是个table)并不是全局的,需要创建多个,这个时候就得模拟类的机制
-------------------------------------------------------------------
-- 拷贝表数据
-- @param b : 原始表
-- @param a : 新表
-------------------------------------------------------------------
-- lua的表默认是引用的,例如a={1,2} b=a b[1]=2 此时a[1]也会等于2
-- 这个函数支持将表真正的拷贝一份,各自可以独立修改
-- 同时支持嵌套的表拷贝,例如a={1,2,{3,4,5}} copy_table(b,a)
-------------------------------------------------------------------
function copy_table(a,b)
    --a = {} 这里不能将a表置为空表,因为这样做会导致a表内存地址的改变
    for key,value in b do
        if type(value)=='table' then
            a[key] = {}
            copy_table(a[key],value)
        else
            a[key]=value
        end
    end
end
-- 公共基类
Object = {}
-- 成员函数形式的new 
function Object:new(o)
    o = o or {} 
    -- Table型数据默认是引用的,所以需要从基类拷贝一份,否则很容易出现莫名奇妙的错误
    for key,value in self do
       if type(value)=='table' then
            if o[key]==nil or o[key]==value then
                o[key]={}
                copy_table(o[key],value)
            end
       end
    end
   
    setmetatable(o,{__index = self})

    return o
end
-- 操作符形式的new 
function new(type,param)
    param = param or {}
    return type:new(param)
end

--原型基类
PrototypeObject = {}

--克隆方法
function PrototypeObject:new(o)
    o = o or {}
    DoClone(o,self)
    return o
end

--克隆方法
--@param destObject 目标对象
--@param srcObject 源对象
function DoClone(destObject,srcObject)
    for key,value in srcObject do
        --目标对象有的元素不拷贝
        --指向目标对象也不拷贝,防止循环引用拷贝出错
        if destObject[key] == nil and value ~= destObject then
            if type(value)=='table' then
                destObject[key] = {}
                DoClone(destObject[key],value)
            else
                destObject[key]=value
            end
        end
    end
end
--继承很简单
local A = Object:new()
local B = A:new()--B即使继承A
--lua面向对象的实现主要是利用了Lua表中__index的特性
lua查找表元素的时候遵循下面三个步骤
1.在表中查找,如果找到,返回该元素,找不到则继续

2.判断该表是否有元表,如果没有元表,返回nil,有元表则继续

3.判断元表有没有__index方法,如果__index方法为nil,则返回nil;如果__index方法是一个表,则重复1、2、3;如果__index方法是一个函数,则返回该函数的返回值 

二:lua中对方法的访问方式,通过.与:的区别
t = {x = 1}    
t.foo = function(t)  
    print(t.x);  
end  
  
local a = {x = 2};  
print(t.foo(a), t:foo(a));  
输出:
2
1
nil
表明用:访问时传入的第一个参数是自己,即self,
其实有时候有疑问,当我们写一个函数的时可以写成
t.foo = function(t)
/////
end
也可以写成
funtiong t:foo()
///
end
这两种写法都没有关系,只是Lua的语法,给Lua的表中添加一个成员
当我们将其模拟成类的时候,会写成第二种,看成表的时候会写成第一种

t = Object:new{x = 1}  
  
function t:foo(a) 
    print(a.x);  
end  
  
local a = {x = 2};  
print(t.foo(self,a), t:foo(a)); 
输出:
2
2
nil 
若我们将t.foo(self,a)中的self去除,就会说a is a nil
通过上面我们可以看出函数写的方式不管你是.还是:都没有影响,只用当你访问的时候是用.还是用:才决定是否默认传入了self,
其实这也是模拟了c++的方式,函数第一个参数默认传入的是self,这个步骤只是编译器帮你做了,自己不知道而已



0 0
原创粉丝点击