lua——元表、元方法、继承
【元表】
元表中的键为事件(event),称值为元方法(metamethod)。
通过函数getmetatable查询不论什么值的元表,通过函数setmetatable替换表的元表。
setmetatable(仅仅能用于table)和getmetatable(用于不论什么对象)
语法:setmetatable (table, metatable),对指定table设置metatable 【假设元表(metatable)中存在__metatable键值。setmetatable会失败】
语法:tmeta = getmetatable (tab)。返回对象的元表(metatable) 【假设元表(metatable)中存在__metatable键值,当返回__metatable的值】
【元方法】
元表能够控制对象的数学运算、顺序比較、连接、取长、和索引操作的行为。
当Lua对某值运行当中一个操作时。检查该值是否含有元表以及对应的事件。
假设有,与该键关联的值(元方法)控制Lua怎样完毕操作。
每一个操作的键是由其名字前缀两个下划线“__”的字符串。比如。操作“加(add)”的键是字符串"__add"。
特别一提,要获取给定对象的元方法。我们使用表达式
metatable(obj)[event]
它应被解读为
rawget(getmetatable(obj) or {}, event)
就是说,訪问一个元方法不会调用其它元方法,并且訪问没有元表的对象不会失败(仅仅是结果为nil)。
"add": + 操作。
以下的getbinhandler函数定义Lua怎样选择二元操作的处理程序。首先尝试第一操作数,假设它的类型未定义该操作的处理程序。则尝试第二操作数。
function getbinhandler (op1, op2, event)
return metatable(op1)[event] or metatable(op2)[event]
end
事件:
add
sub
mul
div
mod
pow
unm 一元操作-
concat 连接操作..
len 取长操作#
eq 同样操作==
lt 小于操作<
le
index 索引訪问table[key],參数table,key
newindex 索引赋值table[key] = value, 參数table, key, value
call lua调用
__index元方法:
依照之前的说法,假设A的元表是B,那么假设訪问了一个A中不存在的成员。就会訪问查找B中有没有这个成员。这个过程大体是这样,但却不全然是这样。实际上,即使将A的元表设置为B。并且B中也确实有这个成员,返回结果仍然会是nil。原因就是B的__index元方法没有赋值。依照我的理解,__index方法是用来确定一个表在被作为元表时的查找方法。
【用户数据和元方法】
Userdata:
A userdata offers a row memory area, with no predefined operations in Lua, which we can use to store anything (分配指定数量的内存在栈上。把数据已用户自己定义的数据结构存放进去)
lua_newuserdata() -- allocates a block of memory with the given size, pushes the corresponding userdatum on the stack, and returns the block address
Metatable:
The usual method to distinguish one type of userdata from other userdata is to create a unique metatable for that type.
Lua code cannot change the metatable of a userdatum, it cannot fake our code (Lua 不能改变userdata里面的metatable,所以userdata的metatable能够用作唯一标示符来识别userdata,这里metatable拿来推断是否传入了正确的userdata參数)
【继承】
cocos2dx里的继承:
function class(classname, ...)
local cls = {__cname = classname} local supers = {...}
for _, super in ipairs(supers) do
local superType = type(super)
assert(superType == "nil" or superType == "table" or superType == "function",
string.format("class() - create class \"%s\" with invalid super class type \"%s\"",
classname, superType)) if superType == "function" then
assert(cls.__create == nil,
string.format("class() - create class \"%s\" with more than one creating function",
classname));
-- if super is function, set it to __create
cls.__create = super
elseif superType == "table" then
if super[".isclass"] then
-- super is native class
assert(cls.__create == nil,
string.format("class() - create class \"%s\" with more than one creating function or native class",
classname));
cls.__create = function() return super:create() end
else
-- super is pure lua class
cls.__supers = cls.__supers or {}
cls.__supers[#cls.__supers + 1] = super
if not cls.super then
-- set first super pure lua class as class.super
cls.super = super
end
end
else
error(string.format("class() - create class \"%s\" with invalid super type",
classname), 0)
end
end cls.__index = cls
if not cls.__supers or #cls.__supers == 1 then
setmetatable(cls, {__index = cls.super})
else
setmetatable(cls, {__index = function(_, key)
local supers = cls.__supers
for i = 1, #supers do
local super = supers[i]
if super[key] then return super[key] end
end
end})
end if not cls.ctor then
-- add default constructor
cls.ctor = function() end
end
cls.new = function(...)
local instance
if cls.__create then
instance = cls.__create(...)
else
instance = {}
end
setmetatableindex(instance, cls)
instance.class = cls
instance:ctor(...)
return instance
end
cls.create = function(_, ...)
return cls.new(...)
end return cls
end
原理就不细说了。改动__index。使得在訪问其成员的时候能遍历全部的supers父类去查找该成员(类似js里的原型链,但那是一条链,这里lua可自由发挥)。
他的第一个參数是类名,后面的參数能够是父表或者函数,函数的话仅仅能有一个,是用来作为创建函数的__create,会在.new的时候被调用。
用法:
local UIScene = class("UIScene")
UIScene.__index = UIScene
function UIScene.extend(target)
local t = tolua.getpeer(target)
if not t then
t = {}
tolua.setpeer(target, t)
end
setmetatable(t, UIScene)
return target
end
function UIScene.create()
local scene = cc.Scene:create()
local layer = UIScene.extend(cc.Layer:create())
layer:init()
scene:addChild(layer)
return scene
end
getpeer/setpeer我还不是非常理解,从网上找到说明留着消化:
Those are tolua functions. The tolua manual (for example here) has explanations for them. tolua.setpeer (object, peer_table) (lua 5.1 only)
Sets the table as the object's peer table (can be nil). The peer table is where all the custom lua fields for the object are stored. When compiled with lua 5.1, tolua++ stores the peer as the object's environment table, and uses uses lua_gettable/settable (instead of lua_rawget/set for lua 5.0) to retrieve and store fields on it. This allows us to implement our own object system on our table (using metatables), and use it as a way to inherit from the userdata object. Consider an alternative to the previous example:
-- a 'LuaWidget' class
LuaWidget = {}
LuaWidget.__index = LuaWidget function LuaWidget:add_button(caption)
-- add a button to our widget here. 'self' will be the userdata Widget
end local w = Widget()
local t = {}
setmetatable(t, LuaWidget) -- make 't' an instance of LuaWidget tolua.setpeer(w, t) -- make 't' the peer table of 'w' set_parent(w) -- we use 'w' as the object now w:show() -- a method from 'Widget'
w:add_button("Quit") -- a method from LuaWidget (but we still use 'w' to call it)
When indexing our object, the peer table (if present) will be consulted first, so we don't need to implement our own __index metamethod to call the C++ functions.
tolua.getpeer (object) (lua 5.1 only)
Retrieves the peer table from the object (can be nil).
lua——元表、元方法、继承的更多相关文章
- 【quick-cocos2d-x】Lua 面向对象(OOP)编程与元表元方法
版权声明:本文为博主原创文章,转载请注明出处. 面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物. 早期的计算机编程是基于面向过程的方法,通过设计一个算法就可以解决当时 ...
- Lua __index元方法
[Lua __index元方法] 当你通过键来访问 table 的时候,如果这个键没有值,那么Lua就会寻找该table的metatable(假定有metatable)中的__index 键.如果__ ...
- Lua的元方法__newindex元方法
上一篇介绍了__index元方法,总结来说:__index元方法是用于处理访问table中不存在的字段时的情况. 而今天,介绍的__newindex元方法,总结来说,就是:用于处理给table中不存在 ...
- lua编程之元表与元方法
一. 前言 lua是一种非常轻量的动态类型语言,在1993年由由Roberto Ierusalimschy.Waldemar Celes 和 Luiz Henrique de Figueiredo等人 ...
- lua metatable和metamethod元表和元方法
Lua中提供的元表是用于帮助Lua数据变量完成某些非预定义功能的个性化行为,如两个table的相加.假设a和b都是table,通过元表可以定义如何计算表达式a+b.当Lua试图将两个table相加时, ...
- lua元表(metatable)和元方法(metamethod)
(一) 元表概念: 引言:Lua中的每个值都有一套预定义的操作集合,如数字相加等.但无法将两个table相加,此时可通过元表修改一个值的行为,使其在面对一个非预定义的操作时执行一个指定操作. 访问机制 ...
- Lua 学习笔记(十一)元表与元方法
在Lua中的每个值都有一套预定义的操作集合.例如可以将数字相加,可以连接字符串,还可以在table中插入一对key-value等.但是我们无法将两个table相加,无法对函数作比较,也无法调用一个字符 ...
- lua元表与元方法
lua中提供的元表(metatable)与元方法(metamethod)是一种非常重要的语法,metatable主要用于做一些类似于C++重载操作符式的功能. lua中提供的元表是用于帮助lua变量完 ...
- lua元表和元方法 《lua程序设计》 13章 读书笔记
lua中每个值都有一个元表,talble和userdata可以有各自独立的元表,而其它类型的值则共享其类型所属的单一元表.lua在创建table时不会创建元表. t = {} print(getmet ...
随机推荐
- 利用CSS、JavaScript及Ajax实现图片预加载的三大方法及优缺点分析
预加载图片是提高用户体验的一个很好方法.图片预先加载到浏览器中,访问者便可顺利地在你的网站上冲浪,并享受到极快的加载速度.这对图片画廊及图片占据很大比例的网站来说十分有利,它保证了图片快速.无缝地发布 ...
- C++类模板的三种特化
说起C++的模板及模板特化, 相信很多人都很熟悉 ,但是说到模板特化的几种类型,相信了解的人就不是很多.我这里归纳了针对一个模板参数的类模板特化的几种类型, 一是特化为绝对类型: 二是特化为引用,指针 ...
- 协定须要双工,可是绑定“WSHttpBinding”不支持它或者因配置不对而无法支持它
协定须要双工,可是绑定"WSHttpBinding"不支持它或者因配置不对而无法支持它 下面两种情况,我都遇到过. 一, < endpoint address =" ...
- PHP json_encode转换空数组为对象
问题描述: php返回json格式的数据,当返回数据的为数组,且key为字符串时,json化后将返回jsonObject,但是如果是空数组,有可能返回的就是jsonArray,数据结构不一致导致端解析 ...
- Ensemble_learning 集成学习算法 stacking 算法
原文:https://herbertmj.wikispaces.com/stacking%E7%AE%97%E6%B3%95 stacked 产生方法是一种截然不同的组合多个模型的方法,它讲的是组合学 ...
- ML—朴素贝叶斯
华电北风吹 日期:2015/12/12 朴素贝叶斯算法和高斯判别分析一样同属于生成模型.但朴素贝叶斯算法须要特征条件独立性如果,即样本各个特征之间相互独立. 一.朴素贝叶斯模型 朴素贝叶斯算法通过训练 ...
- 打通Fedora19的ssh服务
Fedora19的SSH服务是默认关闭的,安装后我们需要打通它. 首先,编辑/etc/ssh/sshd_config,把下面黑体字部分打开注释,如下: # $OpenBSD: sshd_c ...
- MongoDB社区版本和企业版本差别
MongoDB社区版本和企业版本差异主要体现在安全认证.系统认证等方面,具体信息参考下表: 版本特性 社区版本 企业版本 JSON数据模型.自由模式 支持 支持 水平扩展的自动分片功能 支持 支持 内 ...
- shapefile文件的符号化问题
我们都知道,ArcGIS的shp文件只以坐标形式保存地图数据,地图的显示方法则是存储都数据库或地图文件(mxd)中,这一点是深信不疑的. 如果我们打开ArcMap,新建一个普通的地图文件(使用标准的模 ...
- ZH奶酪:【数据结构与算法】并查集基础
1.介绍 并查集是一种树型数据结构,用于处理一些不相交集合的合并问题. 并查集主要操作有: (1)合并两个不相交集合: (2)判断两个元素是否属于同一个集合: (3)路径压缩: 2.常用操作 用fat ...