Lua中利用元表实现类和多态教程

合集下载

0基础lua学习(十六)lua的多态base

0基础lua学习(十六)lua的多态base

0基础lua学习(⼗六)lua的多态base 多态base使⽤lua实现C++类似的多态,看起来略微难了⼀些,这个demo,默认提供了 init类似构造函数的时机。

--base.lua代码--保存类类型的虚表local _class = {}function BaseClass(super)-- ⽣成⼀个类类型local class_type = {}-- 在创建对象的时候⾃动调⽤class_type.__init = falseclass_type.__delete = falseclass_type.super = superclass_type.New = function(...)-- ⽣成⼀个类对象local obj = {}obj._class_type = class_type-- 在初始化之前注册基类⽅法setmetatable(obj, { __index = _class[class_type] })-- 调⽤初始化⽅法dolocal createcreate = function(c, ...)if c.super thencreate(c.super, ...)endif c.__init thenc.__init(obj, ...)endendcreate(class_type, ...)end-- 注册⼀个delete⽅法obj.DeleteMe = function(self)local now_super = self._class_typewhile now_super ~= nil doif now_super.__delete thennow_super.__delete(self)endnow_super = now_super.superendendreturn objendlocal vtbl = {}_class[class_type] = vtblsetmetatable(class_type, {__newindex =--table key valuefunction(t,k,v)vtbl[k] = vend,__index = vtbl, --For call parent method})if super thensetmetatable(vtbl, {__index =function(t,k)local ret = _class[super][k]return retend})endreturn class_typeend--main.lua代码require"base"father = father or BaseClass()function father:__init()print("father:init")endfunction father:Bind()print("father:Bind")endfunction father:play()print("father:play")endson = son or BaseClass(father)function son:__init()print("son:init")endfunction son:Bind()print("son:Bind")endfunction son:UnBind()enda = nila = son:New()a:play()a:Bind()console:father:initson:initfather:playson:Bind多态base解析1.⾸先要明确father = father or BaseClass( )和 son = son or BaseClass(father)有⼀个共同的表local _class = {},也就是虚表。

Lua教程(九):元表与元方法详解

Lua教程(九):元表与元方法详解

Lua教程(九):元表与元⽅法详解Lua中提供的元表是⽤于帮助Lua数据变量完成某些⾮预定义功能的个性化⾏为,如两个table的相加。

假设a和b都是table,通过元表可以定义如何计算表达式a+b。

当Lua试图将两个table相加时,它会先检查两者之⼀是否有元表,然后检查该元表中是否存在__add字段,如果有,就调⽤该字段对应的值。

这个值就是所谓的“元⽅法”,这个函数⽤于计算table的和。

Lua中每个值都有⼀个元表。

table和userdata可以有各⾃独⽴的元表,⽽其它数据类型的值则共享其类型所属的单⼀元表。

缺省情况下,table在创建时没有元表,如:复制代码代码如下:t = {}print(getmetatable(t)) --输出为nil这⾥我们可以使⽤setmetatable函数来设置或修改任何table的元表。

复制代码代码如下:t1 = {}setmetatable(t,t1)assert(getmetatable(t) == t1)任何table都可以作为任何值的元表,⽽⼀组相关的table也可以共享⼀个通⽤的元表,此元表将描述了它们共同的⾏为。

⼀个table甚⾄可以作为它⾃⼰的元表,⽤于描述其特有的⾏为。

在Lua代码中,只能设置table的元表,若要设置其它类型值的元表,则必须通过C代码来完成。

1. 算术类的元⽅法:在下⾯的⽰例代码中,将⽤table来表⽰集合,并且有⼀些函数⽤来计算集合的并集和交集等。

复制代码代码如下:Set = {}local metatable = {} --元表--根据参数列表中的值创建⼀个新的集合function Set.new(l)local set = {}--将所有由该⽅法创建的集合的元表都指定到metatablesetmetatable(set,metatable)for _, v in ipairs(l) doset[v] = trueendreturn setend--取两个集合并集的函数function Set.union(a,b)local res = Set.new{}for k in pairs(a) dores[k] = trueendfor k in pairs(b) dores[k] = trueendreturn resend--取两个集合交集的函数function Set.intersection(a,b)local res = Set.new{}for k in pairs(a) dores[k] = b[k]endreturn resendfunction Set.tostring(set)local l = {}for e in pairs(set) dol[#l + 1] = eendreturn "{" .. table.concat(l,", ") .. "}";endfunction Set.print(s)print(Set.tostring(s))end--最后将元⽅法加⼊到元表中,这样当两个由Set.new⽅法创建出来的集合进⾏--加运算时,将被重定向到Set.union⽅法,乘法运算将被重定向到Set.intersectionmetatable.__add = Set.unionmetatable.__mul = Set.intersection--下⾯为测试代码s1 = Set.new{10,20,30,50}s2 = Set.new{30,1}s3 = s1 + s2Set.print(s3)Set.print(s3 * s1)--输出结果为:--{1, 30, 10, 50, 20}--{30, 10, 50, 20}在元表中,每种算术操作符都有对应的字段名,除了上述的__add(加法)和__mul(乘法)外,还有__sub(减法)、__div(除法)、__unm(相反数)、__mod(取模)和__pow(乘幂)。

lua高级用法

lua高级用法

lua高级用法
Lua的高级用法包括但不限于以下几个方面:
1. 表(table)的高级使用:表是Lua中的核心数据结构,具有灵活性和可变性。

你可以使用表进行类数组的操作,通过默认的索引进行访问;还可以使用特定的方法获取或改变表的长度;更可以利用for循环和pairs函数遍历表中的元素。

2. 函数(function)的高级定义和使用:Lua允许使用函数进行模块化和重用,你还可以使用闭包(closure)来创建私有函数。

3. 协程(coroutine):协程是一种程序组件,它可以在执行过程中挂起,并在以后从挂起点继续执行。

Lua提供了对协程的支持,你可以用它实现异步编程。

4. 错误处理:Lua提供了简单的错误处理机制,你可以使用try/catch语句来捕获和处理错误。

5. 高级I/O:Lua提供了一套完整的I/O库,支持文件和流的读写操作。

6. 自定义数据类型:Lua允许你通过创建新的表作为自定义的数据类型,以扩展或修改现有的数据类型。

7. 元表(metatable):元表提供了一种方式来定义对象的行为。

你可以通过元表来修改或扩展已有的数据类型。

以上只是Lua高级用法的一部分,具体的使用方式会因你的需求和场景而有所不同。

lua 元表和元方法

lua 元表和元方法
local h
if type(table) == "table" then
local v = rawget(table, key)
if v ~= nil then
return v
end
h = metatable(table).__index
metatable(obj)[event]
它应被解读为
rawget(getmetatable(obj) or {}, event)
就是说,访问一个元方法不会调用其他元方法,而且访问没有元表的对象不会失败(只是结果为nil)。
"add": + 操作。
下面的getbinhandler函数定义Lua如何选择二元操作的处理程序。首先尝试第一操作数,如果它的类型没有定义该操作的处理程序,则尝试第二操作数。
if type(op1) == "number" and type(op2) == "number" then
return op1 < op2 -- 数字比较
elseif type(op1) == "string" and type(op2) == "string" then
end
end
end
a > b等价于b < a。
"le": <= 操作。
function le_event (op1, op2)
if type(op1) == "number" and type(op2) == "number" then
return op1 <= op2 -- 数字比较

lua程序设计 10章

lua程序设计 10章

lua程序设计 10章(最新版)目录1.Lua 程序设计的概述2.Lua 语言基础3.控制结构4.函数和模块5.表和元表6.迭代和递归7.集合和散列8.输入输出和错误处理9.面向对象编程10.GPU 编程和扩展库正文Lua 程序设计是一本关于 Lua 编程语言的书籍,全书共分为 10 章,涵盖了 Lua 编程的方方面面。

第一章,Lua 程序设计的概述,主要介绍了 Lua 编程语言的发展历程,特点以及应用领域。

Lua 作为一种轻量级的脚本语言,广泛应用于游戏开发、嵌入式系统、Web 开发等领域。

第二章,Lua 语言基础,主要介绍了 Lua 的基本语法,包括变量、常量、运算符、类型等。

第三章,控制结构,主要介绍了 Lua 的控制结构,包括条件语句、循环语句等。

第四章,函数和模块,主要介绍了 Lua 的函数定义和调用,以及模块的导入和使用。

第五章,表和元表,是 Lua 的核心数据结构,表是 Lua 的一种有序集合,元表是表的一种扩展,可以用来定义表的属性和操作。

第六章,迭代和递归,主要介绍了 Lua 的迭代和递归机制,包括 for 循环、while 循环以及递归函数的定义和调用。

第七章,集合和散列,主要介绍了 Lua 的集合数据结构和散列函数,集合是一种无序的元素集合,散列函数可以用来对集合进行快速查找和插入操作。

第八章,输入输出和错误处理,主要介绍了 Lua 的输入输出函数以及错误处理的机制。

第九章,面向对象编程,主要介绍了 Lua 的面向对象编程机制,包括类、对象、继承、多态等。

第十章,GPU 编程和扩展库,主要介绍了如何使用 Lua 进行 GPU 编程,以及如何使用 Lua 扩展库进行各种操作。

Lua面向对象(实现类的创建和实例化、封装、继承、多态)

Lua面向对象(实现类的创建和实例化、封装、继承、多态)

Lua⾯向对象(实现类的创建和实例化、封装、继承、多态)⽬录1、Lua⾯向对象基础⾯向对象三⼤特性包括:封装、继承、多态。

还有在Lua中如何创建类和实例化,这⾥⼀⼀介绍1.1、Lua类的创建和实例化Test1.lua--name,age就相当于字段。

eat就相当于⽅法person = {name = 'Ffly',age = 20}function person:eat()print( .. '该吃饭饭了,饿死了')end--这个⽅法⽤于实例化使⽤function person:new()local self = {}--使⽤元表,并把__index赋值为person类setmetatable(self,{__index = person})return selfendTest2.lua--加载模块Test1.lua(类似于C#中的using引⽤)--LuaStudio默认从软件根⽬录下加载require "Test1"--实例化person类person1 = person:new()person1:eat() --正常输出1.2、Lua封装--对age字段进⾏封装,使其只能⽤get⽅法访问function newPerson(initAge)local self = {age = initAge};--三个⽅法local addAge = function(num)self.age = self.age + num;endlocal reduceAge = function(num)self.age = self.age - num;endlocal getAge = function(num)return self.age;end--返回时只返回⽅法return {addAge = addAge,reduceAge = reduceAge,getAge = getAge,}endperson1 = newPerson(20)--没有使⽤额外的参数self,⽤的是那⾥⾯的self表--所以要⽤.进⾏访问person1.addAge(10)print(person1.age) --输出nilprint(person1.getAge()) --输出301.3、Lua继承--基类person,boy类继承于personperson = {name = "default",age = 0}function person:eat()print( .. '该吃饭饭了,饿死了')end--使⽤元表的 __index完成继承(当访问不存在的元素时,会调⽤)function person:new(o)--如果o为false或者o为nil,则让o为{}o = o or {}setmetatable(o,self)--设置上⾯self的__index为表personself.__index = selfreturn oend--相当于继承boy = person:new()--name在boy⾥找不到会去person⾥⾯找print() --输出default--修改了person⾥的值,并不会影响boy⾥⾯的值 = 'feifei'print() --输出defaultprint() --输出feifei1.4、Lua多态person = {name = "default",age = 0}--重载--简单⽅法:lua中会⾃动去适应传⼊参数的个数,所以我们可以写在⼀个⽅法⾥⾯function person:eat(food)if food == nil thenprint( .. '该吃饭饭了,饿死了')elseprint( .. '喜欢吃:' .. food)endendfunction person:addAge(num)if num == nil thenself.age = self.age + 1elseself.age = self.age + numendendprint(person:eat())print(person:eat("⼤西⽠"))person:addAge()print(person.age)person:addAge(5)print(person.age)--重写function person:new(o)--如果o为false或者o为nil,则让o为{}o = o or {}setmetatable(o,self)--设置上⾯self的__index为表personself.__index = selfreturn oendboy = person:new() = "Ffly"boy:eat() --调⽤基类eat⽅法--相当于重写eat⽅法function boy:eat()print('⼩男孩' .. .. '快要饿死了')endboy:eat() --调⽤派⽣类eat⽅法2、Lua⾯向对象进阶2.1、class.lua的实现class代码参考于的博客。

lua绑定C++对象系列四——luna模板

lua绑定C++对象系列四——luna模板

lua绑定C++对象系列四——luna模板在系列⽂章⼆三中描述的绑定C++对象基础篇和进阶篇,都有⼀个很⼤的问题,就是每个类需要写⼤量的代码,从类的元表创建、⽅法注册到实例创建,都需要⾃⼰重复写类似的代码。

如果涉及N个不同类,会有⼤量重复的代码,能否创建⼀个模板类,把这些重复的代码进⾏简化,通过模板的⽅式绑定成不同的类?下⾯的luna<T>就是完成这样⼀个壮举,例如针对Car类,只需要luna<Car>::regist(L)即可完成注册。

在lua层⾯ local car = Car()就能⾃动创建Car对象,然后⽅便的通过car.xxx()调⽤成员⽅法。

代码⽂件luna.h1 #include <iostream>2 #include <cstring>3extern"C" {4 #include <lua.h>5 #include <lualib.h>6 #include <lauxlib.h>7 }89using namespace std;1011#define DECLARE_LUNA_CLASS(obj) \12static const char *name;\13static luna<obj>::TMethod methods[];1415#define EXPORT_LUNA_FUNCTION_BEGIN(obj) \16const char* obj::name = #obj;\17 luna<obj>::TMethod obj::methods[] = {1819#define EXPORT_LUNA_MEMBER_INT(obj, member) \20 {#member, nullptr},2122#define EXPORT_LUNA_FUNCTION(obj, func) \23 {#func, &obj::func},2425#define EXPORT_LUNA_FUNCTION_END(obj) \26 {nullptr, nullptr}\27 };2829 template<typename T>30class luna31 {32public:33 typedef struct {T* _u;} TObject;34 typedef int (T::*TPfn)(lua_State* L);35 typedef struct {const char* name; TPfn pf;} TMethod;36public:37static int regist(lua_State* L);38static int create(lua_State* L);39static int call(lua_State* L);40static int gc(lua_State* L);41 };4243 template<typename T>44int luna<T>::regist(lua_State* L)45 {46//原表Shape47if (luaL_newmetatable(L, T::name))48 {49//注册Shape到全局50 lua_newtable(L);51 lua_pushvalue(L, -1);52 lua_setglobal(L, T::name);5354//设置Shape的原表,主要是__call,使其看起来更像C++初始化55 lua_newtable(L);56 lua_pushcfunction(L, luna<T>::create);57 lua_setfield(L, -2, "__call");58 lua_setmetatable(L, -2);59 lua_pop(L, 1); //这时候栈只剩下元表61//设置元表Shape index指向⾃⼰62 lua_pushvalue(L, -1);63 lua_setfield(L, -2, "__index");64 lua_pushcfunction(L, luna<T>::gc);65 lua_setfield(L, -2, "__gc");66 }67return0;68 }6970 template<typename T>71int luna<T>::create(lua_State* L)72 {73 lua_remove(L, 1);74 TObject* p = (TObject*)lua_newuserdata(L, sizeof(TObject));75 p->_u = new T();7677 luaL_getmetatable(L, T::name);78 lua_setmetatable(L, -2);7980 luaL_getmetatable(L, T::name);81for (auto* l = T::methods; l->name; l++)82 {83 lua_pushlightuserdata(L,(void*)l);84 lua_pushlightuserdata(L,(void*)p);85 lua_pushcclosure(L, luna<T>::call, 2);86 lua_setfield(L, -2, l->name);87 }8889 lua_pop(L, 1);9091return1;92 }9394 template<typename T>95int luna<T>::call(lua_State* L)96 {97 TMethod* v = (TMethod*)lua_topointer(L, lua_upvalueindex(1));98 cout<<"luna<T>::call:"<<v->name<<endl;99100 TObject* p = (TObject*)lua_topointer(L, lua_upvalueindex(2));101102103return ((p->_u)->*(v->pf))(L);104 }105106 template<typename T>107int luna<T>::gc(lua_State* L)108 {109 TObject* p = (TObject*)lua_touserdata(L, 1);110 (p->_u)->~T();111return0;112 }通过上述代码发现:luna<T>模板类,把⼀些⾏为固化下来了。

lua 元方法

lua 元方法

lua 元方法Lua元方法是Lua语言中的一种特殊机制,它能够让我们通过重载一些特定的操作符来实现自定义的行为,使得我们的代码更加灵活、易于理解和维护。

在本文中,我们将深入探讨Lua元方法的相关概念、使用方法和实际应用场景,帮助读者更好地理解和掌握这一重要的特性。

一、什么是Lua元方法在Lua语言中,元方法是一种特殊的函数,它们与特定的操作符相关联,当执行这些操作符时,Lua会自动调用相应的元方法。

通过重载这些元方法,我们可以改变Lua默认的行为,并实现自定义的操作方式。

例如,我们可以通过重载加号操作符来实现两个表的合并,重载取值操作符来实现自定义的属性访问方式等等。

Lua中的元方法通常以__开头和结尾,例如__add、__index、__newindex等。

这些元方法都是Lua内部预定义的,它们与特定的操作符相关联,当执行这些操作符时,Lua会自动调用相应的元方法。

我们也可以自定义元方法,通过设置元表(metatable)来将自定义的元方法与特定的操作符关联起来。

二、Lua元方法的使用方法Lua元方法的使用方法非常简单,我们只需要定义一个元表,并将元表与需要进行操作的对象关联即可。

例如,我们可以通过如下代码定义一个元表:```lualocal mt = {}```然后,我们可以通过设置元表来将元表与某个对象关联起来,例如:```lualocal t = {}setmetatable(t, mt)```这样,当我们对这个对象执行某个操作时,Lua就会自动调用与该操作关联的元方法。

例如,当我们对两个表进行加法操作时,Lua 会自动调用__add元方法来实现加法操作,如果我们定义了自定义的__add函数,就可以改变加法操作的行为。

下面是一些常用的元方法及其对应的操作符:| 元方法 | 操作符 | 说明 || --- | --- | --- || __add | + | 加法操作 || __sub | - | 减法操作 || __mul | * | 乘法操作 || __div | / | 除法操作 || __mod | % | 取模操作 || __pow | ^ | 求幂操作 || __unm | - | 取负操作 || __concat | .. | 连接操作 || __eq | == | 相等操作 || __lt | < | 小于操作 || __le | <= | 小于等于操作 || __index | [] | 取值操作 || __newindex | [] | 赋值操作 || __call | () | 函数调用操作 |通过重载这些元方法,我们可以实现各种自定义的操作行为。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
相关文档
最新文档