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 ...
随机推荐
- java获取指定文件夹下的所有文件名
package com.henu.util; import java.io.File; public class TakeFilePathAndName { public static void ma ...
- c++ placement new概念
参考:http://www.cnblogs.com/Clingingboy/archive/2013/04/26/3044910.html 转:http://bbs.chinaunix.net/thr ...
- Triangular numbers
http://codeforces.com/problemset/problem/47/A Triangular numbers time limit per test 2 seconds memor ...
- 【Nodejs】理想论坛帖子爬虫1.02
在1.01版本中,我发现各回调函数找到数据后再插入数据库有个竞争问题不好解决,如果等所有回调都完成也没有好的处理方法,因为启动不止一处启动了新的TopicSpider实例. 于是我决定把读数据和写DB ...
- 安装Ubuntu 桌面版 12.04 LTS 过程之记录
[下载ISO文件刻录到光盘上] 1.首先从http://www.ubuntu.com/download/desktop/zh-CN找到合适的版本下载. 2.完毕后,将ISO文件放好.然后启动nero, ...
- linux下mysql-5.5.15安装详细步骤
linux下mysql-5.5.15安装详细步骤 注:该文档中用到的目录路径以及一些实际的值都是作为例子来用,具体的目录路径以各自安装时的环境为准 mysql运行时需要一个启动目录.一个安装目录和一个 ...
- Android 之数据传递小结
Android开发中,在不同模块(如Activity)间经常会有各种各样的数据需要相互传递,常用的的有五种传递方式.它们各有利弊,有各自的应用场景.下面分别介绍一下: 1. Intent对象传递简单数 ...
- C# WebRequest处理Https请求
http://www.cnblogs.com/youlechang123/archive/2013/03/23/2976630.html 正常情况下,处理https和http没有什么区别,如以下代码, ...
- Cannot load supported formats: Cannot run program "svn"
Cannot load supported formats: Cannot run program "svn" CreateTime--2018年4月26日11:32:37 A ...
- Knockout自定义绑定my97datepicker
/* my97datepicker 时间格式'yyyy-MM-dd HH-mm-ss' */ ko.bindingHandlers.datetimes = { init: function (elem ...