在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
Lua本身是没有class之类的关键字的,但是我们可以巧妙利用function也是值和table的特性来实现面向对象的特性。 Lua中的类也是一个table对象,下面我们看看一个简单的类的定义: 1 People = {}--定义表 People 2 3 --添加方法的第一种方式 4 People.talk = function() 5 print("people talk.") 6 end 7 8 --添加方法的第二种方式 9 function People.say() 10 print("people say.") 11 end 12 13 People.talk()--people talk. 14 People.say()--people say. 我们发现添加一个方法有两种方式,这两种方式的效果都是一致的,至于使用哪种就看个人喜好了。 通过拷贝创建实例不知道大家发现没有,上面的示例中并没有创建实例这个步骤,而在面向对象中,类是需要创建实例来使用的,下面我们就用复制的方法来创建实例: 1 --克隆一个表 2 function clone(obj) 3 local instance = {} 4 5 for key, var in pairs(obj) do 6 instance[key] = var 7 end 8 9 return instance; 10 end 11 12 People = {}--定义表 People 13 14 --定义方法 15 People.talk = function() 16 print("people talk.") 17 end 18 19 --创建 People 的实例 20 local p = clone(People) 21 p.talk()--people talk. 构造函数我们发现虽然可以创建实例了,但是却没有构造函数,下面我们把构造函数也添加进去: 1 --克隆一个表 2 function clone(obj) 3 local instance = {} 4 5 for key, var in pairs(obj) do 6 instance[key] = var 7 end 8 9 return instance; 10 end 11 12 People = {}--定义表 People 13 14 --定义构造函数 15 People.new = function(name) 16 local ins = clone(People) 17 ins.name = name; 18 return ins 这里引入了一个新的变量self和“:”符号,下面我们来说说: selfself作为第一个参数表示调用则本身。 .号和:号调用时为了传递调用者本身,所以第一个参数需要将自身传入,这是.号的写法; 如果使用:号,则默认第一个参数传入调用者本身,无需我们再写第一个参数了,我们可以从第二个参数开始写,但是函数声明时仍然要写第一个参数self的。 定义函数时也可以使用:号进行定义,这样定义方法时也可以省略self参数,但是写法只能写成function tab:foo() end这样的形式,如下: 1 obj = {name = "Li Lei"} 2 --.号的写法和调用 3 obj.foo1 = function() 4 print "foo1" 5 end 6 function obj.foo2(self) 7 print(self.name.."foo2") 8 end 9 obj.foo1()--foo1 10 obj.foo2(obj)--Li Leifoo2 11 --:号的写法和定义 12 --[[注释掉的这种写法是不允许的 13 obj:foo3 = function() 14 print(self.name.."foo3") 15 end 16 ]] 17 function obj:foo4() 18 print(self.name.."foo4") 19 end 20 obj:foo4()--Li Leifoo4 继承下面我们来看看如何实现类的继承: 1 --克隆一个表 2 function clone(obj) 3 local instance = {} 4 5 for key, var in pairs(obj) do 6 instance[key] = var 7 end 8 9 return instance; 10 end 11 12 People = {}--定义表 People 13 14 --定义构造函数 15 People.new = function(name) 16 local ins = clone(People) 17 ins.name = name; 18 return ins 19 end 20 21 --定义方法 22 People.talk = function(self) 23 print(self.name.." talk.") 24 end 25 26 --定义方法2 27 People.talk2 = function(self) 28 print(self.name.." talk2.") 29 end 30 31 --创建 People 的实例 32 local p = People.new("Li Lei") 33 p.talk(p)--people talk. 34 p:talk()--使用 : 号可以省略 self 的填写, 效果和上一行一致 35 36 --下面是关于继承的实现 37 38 --将 origin 表的值复制到 dist 表中 39 function copy(origin, dist) 40 for key, var in pairs(origin) do 41 dist[key] = var 42 end 43 end 44 45 Man = {}--定义表 Man, 继承自 People 46 47 Man.new = function(name) 48 local ins = People.new(name)--创建继承的类, 这样就拥有了继承类的所有属性 49 copy(Man, ins)--将 Man 的属性附加到实例 50 return ins 51 end 52 53 --定义方法 54 Man.say = function() 55 print("Man say!") 56 end 57 58 --重写方法 59 Man.talk2 = function(self) 60 print(self.name.." talk2. (Man)") 61 end 62 63 --创建 Man 的实例 64 local m = Man.new("Han Meimei") 65 m:talk()--Han Meimei talk. 66 m:talk2()--Han Meimei talk2. (Man) 67 m:say()--Man say! 简单来说,就是先创建父类的实例,然后把新类的所有属性都拷贝到刚创建的实例上即可。 通过函数闭包的实现我们可以通过在函数内定义函数的方式来实现面向对象的特性: 1 --定义方法直接返回表的实例 2 function People(name) 3 local ins = {}--创建表 4 5 --初始化函数 6 local function init() 7 ins.name = name 8 end 9 10 --定义方法 11 ins.talk = function() 12 print(ins.name.." talk.") 13 end 14 15 --定义带参数的方法 16 ins.talk2 = function(content) 17 print(ins.name.." talk "..content..".") 18 end 19 20 -- self 可以省去了, 因为可以通过闭包的特性获取到, 或者如果要统一 : 符号可以这么写 21 ins.talk3 = function(self, content) 22 print(self.name.." talk "..content..".") 23 end 24 25 init()--调用初始化函数 26 27 return ins 28 end 29 30 --创建对象 31 p = People("Li Lei") 32 p:talk()--没有参数可以这么写 33 p.talk() 34 35 --p:talk2("hello")--没有 self 参数不能这么调用了 36 p.talk2("hello") 37 38 p:talk3("hello 2") 39 p.talk3(p, "hello 2") 这种写法的运行效率略低于上一种方法,但是却更加清晰,在实际使用时推荐使用该方法来编写类。 继承使用这种写法也可以实现类的继承,如下: 1 --定义方法直接返回表的实例 2 function People(name) 3 local ins = {}--创建表 4 5 --初始化函数 6 local function init() 7 ins.name = name 8 end 9 10 --定义方法 11 ins.talk = function() 12 print(ins.name.." talk.") 13 end 14 15 --定义带参数的方法 16 ins.talk2 = function(content) 17 print(ins.name.." talk "..content..".") 18 end 19 20 -- self 可以省去了, 因为可以通过闭包的特性获取到, 或者如果要统一 : 符号可以这么写 21 ins.talk3 = function(self, content) 22 print(self.name.." talk "..content..".") 23 end 24 25 init()--调用初始化函数 26 27 return ins 28 end 29 30 --下面是继承的代码 31 32 function Man(name) 33 local ins = People(name)--关键: 创建一个 People 类的实例 34 35 --添加新项目 36 ins.say = function() 37 print(ins.name.." say.") 38 end 39 40 --覆写老方法 41 ins.talk = function() 42 print(ins.name.." talk. (Man)") 43 end 44 45 return ins 46 end 47 48 m = Man("Han Meimei") 49 m.say()--Han Meimei say. 50 m.talk()--Han Meimei talk. (Man) 其实就是创建父类的对象后添加新的属性,比较容易理解。 |
请发表评论