Lua学习笔记(五):面向对象的实现
2015-08-07 16:05
239 查看
Lua本身是没有class之类的关键字的,但是我们可以巧妙利用function也是值和table的特性来实现面向对象的特性。
我们发现添加一个方法有两种方式,这两种方式的效果都是一致的,至于使用哪种就看个人喜好了。
这里引入了一个新的变量self和“:”符号,下面我们来说说:
如果使用:号,则默认第一个参数传入调用者本身,无需我们再写第一个参数了,我们可以从第二个参数开始写,但是函数声明时仍然要写第一个参数self的。
定义函数时也可以使用:号进行定义,这样定义方法时也可以省略self参数,但是写法只能写成function tab:foo() end这样的形式,如下:
简单来说,就是先创建父类的实例,然后把新类的所有属性都拷贝到刚创建的实例上即可。
这种写法的运行效率略低于上一种方法,但是却更加清晰,在实际使用时推荐使用该方法来编写类。
其实就是创建父类的对象后添加新的属性,比较容易理解。
通过复制表的实现
Lua中的类也是一个table对象,下面我们看看一个简单的类的定义:People = {}--定义表 People --添加方法的第一种方式 People.talk = function() print("people talk.") end --添加方法的第二种方式 function People.say() print("people say.") end People.talk()--people talk. People.say()--people say.
我们发现添加一个方法有两种方式,这两种方式的效果都是一致的,至于使用哪种就看个人喜好了。
通过拷贝创建实例
不知道大家发现没有,上面的示例中并没有创建实例这个步骤,而在面向对象中,类是需要创建实例来使用的,下面我们就用复制的方法来创建实例:--克隆一个表 function clone(obj) local instance = {} for key, var in pairs(obj) do instance[key] = var end return instance; end People = {}--定义表 People --定义方法 People.talk = function() print("people talk.") end --创建 People 的实例 local p = clone(People) p.talk()--people talk.
构造函数
我们发现虽然可以创建实例了,但是却没有构造函数,下面我们把构造函数也添加进去:--克隆一个表 function clone(obj) local instance = {} for key, var in pairs(obj) do instance[key] = var end return instance; end People = {}--定义表 People --定义构造函数 People.new = function(name) local ins = clone(People) ins.name = name; return ins end --定义方法 People.talk = function(self) print(self.name.." talk.") end --创建 People 的实例 local p = People.new("Li Lei") p.talk(p)--people talk. p:talk()--使用 : 号可以省略 self 的填写, 效果和上一行一致
这里引入了一个新的变量self和“:”符号,下面我们来说说:
self
self作为第一个参数表示调用则本身。.号和:号
调用时为了传递调用者本身,所以第一个参数需要将自身传入,这是.号的写法;如果使用:号,则默认第一个参数传入调用者本身,无需我们再写第一个参数了,我们可以从第二个参数开始写,但是函数声明时仍然要写第一个参数self的。
定义函数时也可以使用:号进行定义,这样定义方法时也可以省略self参数,但是写法只能写成function tab:foo() end这样的形式,如下:
obj = {name = "Li Lei"} --.号的写法和调用 obj.foo1 = function() print "foo1" end function obj.foo2(self) print(self.name.."foo2") end obj.foo1()--foo1 obj.foo2(obj)--Li Leifoo2 --:号的写法和定义 --[[注释掉的这种写法是不允许的 obj:foo3 = function() print(self.name.."foo3") end ]] function obj:foo4() print(self.name.."foo4") end obj:foo4()--Li Leifoo4
继承
下面我们来看看如何实现类的继承:--克隆一个表 function clone(obj) local instance = {} for key, var in pairs(obj) do instance[key] = var end return instance; end People = {}--定义表 People --定义构造函数 People.new = function(name) local ins = clone(People) ins.name = name; return ins end --定义方法 People.talk = function(self) print(self.name.." talk.") end --定义方法2 People.talk2 = function(self) print(self.name.." talk2.") end --创建 People 的实例 local p = People.new("Li Lei") p.talk(p)--people talk. p:talk()--使用 : 号可以省略 self 的填写, 效果和上一行一致 --下面是关于继承的实现 --将 origin 表的值复制到 dist 表中 function copy(origin, dist) for key, var in pairs(origin) do dist[key] = var end end Man = {}--定义表 Man, 继承自 People Man.new = function(name) local ins = People.new(name)--创建继承的类, 这样就拥有了继承类的所有属性 copy(Man, ins)--将 Man 的属性附加到实例 return ins end --定义方法 Man.say = function() print("Man say!") end --重写方法 Man.talk2 = function(self) print(self.name.." talk2. (Man)") end --创建 Man 的实例 local m = Man.new("Han Meimei") m:talk()--Han Meimei talk. m:talk2()--Han Meimei talk2. (Man) m:say()--Man say!
简单来说,就是先创建父类的实例,然后把新类的所有属性都拷贝到刚创建的实例上即可。
通过函数闭包的实现
我们可以通过在函数内定义函数的方式来实现面向对象的特性:--定义方法直接返回表的实例 function People(name) local ins = {}--创建表 --初始化函数 local function init() ins.name = name end --定义方法 ins.talk = function() print(ins.name.." talk.") end --定义带参数的方法 ins.talk2 = function(content) print(ins.name.." talk "..content..".") end -- self 可以省去了, 因为可以通过闭包的特性获取到, 或者如果要统一 : 符号可以这么写 ins.talk3 = function(self, content) print(self.name.." talk "..content..".") end init()--调用初始化函数 return ins end --创建对象 p = People("Li Lei") p:talk()--没有参数可以这么写 p.talk() --p:talk2("hello")--没有 self 参数不能这么调用了 p.talk2("hello") p:talk3("hello 2") p.talk3(p, "hello 2")
这种写法的运行效率略低于上一种方法,但是却更加清晰,在实际使用时推荐使用该方法来编写类。
继承
使用这种写法也可以实现类的继承,如下:--定义方法直接返回表的实例 function People(name) local ins = {}--创建表 --初始化函数 local function init() ins.name = name end --定义方法 ins.talk = function() print(ins.name.." talk.") end --定义带参数的方法 ins.talk2 = function(content) print(ins.name.." talk "..content..".") end -- self 可以省去了, 因为可以通过闭包的特性获取到, 或者如果要统一 : 符号可以这么写 ins.talk3 = function(self, content) print(self.name.." talk "..content..".") end init()--调用初始化函数 return ins end --下面是继承的代码 function Man(name) local ins = People(name)--关键: 创建一个 People 类的实例 --添加新项目 ins.say = function() print(ins.name.." say.") end --覆写老方法 ins.talk = function() print(ins.name.." talk. (Man)") end return ins end m = Man("Han Meimei") m.say()--Han Meimei say. m.talk()--Han Meimei talk. (Man)
其实就是创建父类的对象后添加新的属性,比较容易理解。
相关文章推荐
- 在VS中测试Lua项目
- quick-lua AssetsManager 热更新代码
- 【Lua】coroutine
- lua本学习笔记功能
- 【Lua、LuaJIT、tolua++、lua for windows】这几个到底有什么关系?!
- 为什么要使用ngx_lua
- Lua学习笔记(四):表和数组
- lua_code_cache开关
- Lua笔记7-闭包2
- leetcode_Evaluate Reverse Polish Notation
- leetcode_Evaluate Reverse Polish Notation
- lua 中删除table中的多个元素
- [sublime]安装插件配置lua
- Lua元表和元方法
- Lua学习笔记(三):函数和闭包
- expected number,sequence,or string.map evaluated instead of freemarker.template.smplehash
- nmap 缺少module 'citrixxml'以及citrixxml.lua的修补
- PLT:说说Evaluation strategy
- lua 三元运算符的使用
- Lua实现类的封装