wordpress 网站图标设置,棋牌游戏平台,邯郸有没有专门做写字楼的网站,二级建造师执业资格考试前段时间对平台的任务感兴趣#xff0c;其要求是一周内12篇博文#xff0c;尝试了之后发现还是太敷衍了#xff0c;之后还是回归到内容本身上来#xff0c;尽量保证一篇博文的内容能涵盖足够多的知识点或者足够深的思考成分。
面向对象
面向对象主要有三个方面#xff1…前段时间对平台的任务感兴趣其要求是一周内12篇博文尝试了之后发现还是太敷衍了之后还是回归到内容本身上来尽量保证一篇博文的内容能涵盖足够多的知识点或者足够深的思考成分。
面向对象
面向对象主要有三个方面封装、继承和多态。Lua若做到了这三点则认为是也具有面向对象的特征。Lua可以通过表来实现上面三个特征。
类
类本身的概念就是创建对象的模板。然而Lua本身不存在类的概念但是可以创建一个原型prototype对象当调用不属于对象的某些操作时会最先到prototype中查找这些操作。在lua中若想要对象b作为对象a的prototype只需要以下代码
setmetatable(a, {__index b})
继承
有了index后在a域找不到的相关属性就会选择在b域查找。如若有更多的对象选择继承b则覆写以上代码即可此时的b就被用来当作是prototype了。比如如下实例代码可选择将Account作为prototype对象
Account {}
Account.balance 0
function Account.new (o)o o or {} -- create object if user does not provide one setmetatable(o, Account)Account.__index Accountreturn o
endfunction Account:deposit (v)self.balance self.balance v
enda Account.new{balance 100}
a:deposit(100)
print(a.balance) --200
lua面向对象有一个有趣的方式就是不需要创建新类去指定新的对象行为可以直接在对象中实现相关操作即可比如上面的a对象可以直接赋予其新的函数
function a:NewBalance()self.balance 0
end
print(a.balance) -- 200
a:NewBalance()
print(a.balance) -- 0
也可以用相同方式实现多重继承即实现index metamethod使其在多个父类中查找子类不存在的域
function search (k, plist) for i1, #plist dolocal v plist[i][k] -- try i-th superclass if v then return v endend
endfunction createClass(...)local arg {...}local c {}setmetatable(c, {__index function (t, k)return search(k, arg)end})
end
privacy封装
lua本身不具有私有性访问机制。lua设计初衷是小型到中型的程序设计避免太冗余和太多的人为限制。但是我们依然可以有方案实现私有封装操作创建一个函数工厂内设状态和闭包外部只能获取到return的函数table而没有状态
function newAccount (initialBalance) local self {balance initialBalance} local withdraw function (v) self.balance self.balance - v end local deposit function (v) self.balance self.balance v end local getBalance function () return self.balance endreturn { withdraw withdraw, deposit deposit, getBalance getBalance }
end
如上所示除了函数newAccount内部可控制balance变量以外都无法再对balance进行操作外部只能调用函数接口。
C API
C API是一个C代码与Lua进行交互的函数集分为以下几个部分读写Lua全局变量的函数调用Lua函数的函数运行Lua代码片段的函数注册C函数然后可在Lua中被调用的函数等。
在 C 和 Lua 之间通信关键内容在于一个虚拟的栈。几乎所有的 API 调用都是对栈上的值进行操作所有 C 与 Lua 之间的数据交换也都通过这个栈来完成。另外你也可以使用栈来保存临时变量。栈的使用解决了 C 和 Lua 之间两个不协调的问题第一Lua 会自动进行垃圾收集而 C 要求显式的分配存储单元两者引起的矛盾。第二Lua 中的动态类型和 C 中的静态类型不一致引起的混乱。
堆栈
Lua和C之间交互主要面临两个问题一个是内存管理一个是静态类型和动态类型的不一致性。比如a[k] v这一段代码k和v很可能是好几种不同的类型而且由于metatable的存在a也可能会有不同的类型。如果不同类型之间的赋值函数组合在一起很有可能需要几十个不同的函数来完成这一个操作。
当然我们可以在C侧声明union类型解决该问题倘若我们采用settable函数来实现a[k] v这段代码
void lua_settable (lua_Value a, lua_Value k, lua_Value v);
但是这会面临另一个问题内存管理。如果把lua值保存在C侧lua引擎便不清楚这个值是否还在使用很可能会误认为某个值是垃圾从而收集它。并且lua的这个动态类型是非常复杂的映射到其他语言会非常困难lua设计初衷并非只是C/C还要和其他主流语言比如Java进行交互不可能每一个语言都要完成类似这种的转换。
于是Lua API实现了一个抽象的栈在Lua和C之间交换值。无论你何时想要从 Lua 请求一个值比如一个全局变量的值调用 Lua被请求的值将会被压入栈。无论你何时想要传递一个值给 Lua首先将这个值压入栈然后调用 Lua这个值将被弹出。虽然我们需要函数将C类型压入栈和函数从栈上取值但是我们至少是避免了组合爆炸。而且这个栈由lua管理垃圾回收器知道哪个值在被C使用。
Lua侧严格采用先进后出的方式操作栈它只会改变栈顶部分C侧却可以查询、删除、插入栈上的任何元素。
压入元素
可以将每种可用C来描述的Lua类型压栈
void lua_pushnil (lua_State *L);
void lua_pushboolean (lua_State *L, int bool);
void lua_pushnumber (lua_State *L, double n);
void lua_pushlstring (lua_State *L, const char *s, size_t length);
void lua_pushstring (lua_State *L, const char *s);
任意的字符串char*类型允许包含\0字符用 lua_pushlstring它要求一个明确的长度作为参数。以\0结束的字符串const char*用 lua_pushstring。
无论何时压入一个元素到栈上都需要确保在栈上有空间来做这件事情。可以调用下面函数来检测栈上是否有足够需要的空间。
int lua_checkstack (lua_State *L, int sz);
查询元素
API用索引访问栈内元素。第一个入栈的索引是1栈顶是-1-2指的是栈顶下方的那个元素。通过lua_isnumber/lua_isstring等等函数来判断栈内某个元素是否是指定类型
int lua_is... (lua_State *L, int index);
lua_isnumber 和 lua_isstring 函数不检查这个值是否是指定的类型而是看它是否能被转换成指定的那种类型。例如任何数字类型都满足 lua_isstring。
另外通过lua_tonumber/lua_tostring等函数实现对类型的转换
int lua_toboolean (lua_State *L, int index);
double lua_tonumber (lua_State *L, int index);
const char * lua_tostring (lua_State *L, int index);
size_t lua_strlen (lua_State *L, int index);
注意const修饰符包括上方lua_pushstring函数都意味着lua不允许将指向字符串的指针保存到访问他们的外部函数中。
其他堆栈操作
通过以下函数完成普通的堆栈操作
int lua_gettop (lua_State *L);
void lua_settop (lua_State *L, int index);
void lua_pushvalue (lua_State *L, int index);
void lua_remove (lua_State *L, int index);
void lua_insert (lua_State *L, int index);
void lua_replace (lua_State *L, int index);
顾名思义gettop获取堆栈元素个数settop设置栈大小pushvalue复制索引index位置上的元素到栈顶remove移除指定index位置上的元素insert将栈顶元素插入到index位置上replace将栈顶元素弹出并设置到指定index位置上。