在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
百度搜索一下,给出出的解决方案和学习帖子很多,可是我还是有很多的问题! (1)什么是面向对象? (2)lua中怎么实现面向对象? (3)什么样的实现既简单又能完成我的功能? (4)一定要按照c++的方式实现类的继承吗? 能力有限,在学习lua面向对象的时候我比较喜欢两种实现方式: 1. 简单粗暴的实现 参考[1]:参考同事的方法,如果借鉴、转载请注明 在lua中,我们知道table是万能的一个类型,当我们用table实现一个基类和子类的时候,他们都是确确实实存在的一个个table,都是有地址的。不会说像c++一样,类定义是类定义,只有new出来才是真正可以使用的,而lua却不是这样。所以,最简单的一种方法就是,每次继承基类的时候,直接copy基类的所有内容,函数除外,其他的成员都重新复制一遍,如果是table的话重新构建一个,并且把内容拷贝过来。代码如下: --lua面向对象:简单粗暴的实现 function copytable(tbArg) local tbCollsion = {} --local的作用域问题 local copy copy = function (obj) if type(obj) ~= "table" then return obj; end --检查是否有嵌套循环的table if tbCollsion[obj] then return tbCollsion[obj]; end local tbNew = {} tbCollsion[obj] = tbNew; --递归复制 for k, v in pairs(obj) do tbNew[k] = copy(v); end --复制完之后,元表关系也要保留下来 return setmetatable(tbNew, getmetatable(obj)) end return copy(tbArg); end function inherit(tbBase, tbClass) --复制基类 local tbNew = copytable(tbBase) local tm = {} tm.__index = tbClass; setmetatable(tbNew, tm) --修改tbBase为tbClass中的成员或者新增加tbClass中的成员 if tbClass then for k, v in pairs(tbClass) do tbNew[k] = v end end return tbNew; end --使用 local tbObject = {} local tbFruit = inherit(tbObject) local tbApple = inherit(tbFruit) local tbBanana = inherit(tbFruit) local tbBanana1 = inherit(tbFruit) local tbBanana2 = inherit(tbFruit, tbBanana1)
优点: (1)好理解 (2)好用,不会出现共用一个table引用,导致其中一个修改影响了另外一个 (3)共享函数引用 缺点: (1)真正意义上的面向对象,继承等概念不清晰 (2)一个子类new多个对象的概念是没有的,和继承已经混在了一起,所以如果要实现new多个对象的话,有代码冗余
2. 概念意义上的实现 参考[2]:云风的blog,如果借鉴、转载请注明 这种从概念上实现面向对象的方法做到以下几点: (1)有类定义和对象的概念,类定义通过new来创建对象,并且同时调用自己的构造函数 (2)子类可以访问基类的成员函数 (3)类定义不能够调用函数(除了new之外),只有对象才能调用函数 (4)构造函数调用有和c++一样的层级关系,先调用父类的构造函数,再调用子类的构造函数 --lua面向对象:概念意义上的实现 local _class={} function class(super) local class_type={} --注意:因为重载了__newindex函数, 所以ctor不要定义为nil class_type.ctor=false class_type.super=super class_type.new=function(...) local obj={} --下面的块只做了一件事:依次从父类到当前子类调用构造函数ctor do local create create = function(c,...) if c.super then create(c.super,...) end if c.ctor then c.ctor(obj,...) end end create(class_type,...) end setmetatable(obj,{ __index=_class[class_type] }) return obj end --新加成员:防止定义类调用函数 local vtbl={} _class[class_type]=vtbl setmetatable(class_type,{__newindex= function(t,k,v) vtbl[k]=v end }) --只有定义类修改了__newindex --vbtl只属于定义类 --new出来的对象共享所有定义类的引用,但独享自己新增加的成员变量 if super then setmetatable(vtbl,{__index= function(t,k) local ret=_class[super][k] vtbl[k]=ret return ret end }) end return class_type end 说明几点: (1)只有定义类修改了__newindex 有点: (1)概念上更加清晰,熟悉c++面向对象的很容易了解这个继承的关系 (2)写法上感觉很牛逼,做到了定义不能调用函数这一点 (3)共享函数引用 缺点: (1)概念上清晰的成本是要更多的时间去理解 (2)虽然做到了c++类定义和对象上的概念区别,但是还是有多东西没有实现 (3)对象也可以定义自己的函数,这一点就直接打破了区分定义和对象的本源,但是价值还是有的 (4)所有new出来对象共享类定义的引用对象,包括不需要复用的函数和table。由此多个对象共享一个定义的table很是个问题! * 针对(4),可以通过实现定义的init函数,在init函数给不同的对象初始化不同的数据,即使是table!
参考: [1]同事 [2]http://blog.codingnow.com/cloud/LuaOO |
请发表评论