LUA中的冒号、点和self
在Lua编程中,经常会看到有时用点号定义一个table的成员函数,有时却用冒号,在调用的时候也是如此。那么点号和冒号在使用上有什么区别呢?它们与self之间又是什么样的关系呢?稍安勿躁,接下来谜底将一一为你揭开。
下面先看一个例子
Class = {}
Class.__index = Class
function Class.new(x,y)
local cls = {}
setmetatable(cls, Class)
cls.x = x
cls.y = y
return cls
end
function Class:test()
-- 等价于
-- function Class.test(self)
print(self.x,self.y)
end
object = Class.new(10,20)
object:test() --10 20
-- 等价于
object.test(object) --10 20
可以看到:
(1)定义的时候:Class:test()与 Class.test(self)是等价的;
(2)调用的时候:object:test() 与object.test(object)等价。
但是,一定要小心了,如果我们把例子中代码做一个小小的改动:
object = Class.new(10,20)
改为
object = Class:new(10,20)
猜一下最终的输出结果是什么?
最终的输出结果:
table: 00FFE788 10
table: 00FFE788 10
你是不是大吃一惊了,输出的结果跟我们的预期完全就是天壤之别。那为什么会得到这样的输出结果呢?深层次的原因是什么?下面一一道来。
在这里,我们在调用的时候将点号改为了冒号,使用冒号时,会隐性传递一个self参数,它表示的是调用对象,这样一来,Class:new(10, 20)这样的函数调用实际上有3个实参,分别是self,10,20,但是function Calss.new(x, y)这样用点号实现的函数定义实际上只有2个形参,这样传参的结果是
self ——> x
10 ——> y
20 ——> 丢弃
因此,最终我们打印出来的x和y的值就是self和10,而self实际就是table Class。如果我们把Class.new方法稍微修改一下如下:
function Class.new(self, x,y)
local cls = {}
setmetatable(cls, Class)
cls.x = x
cls.y = y
return cls
end
或者改为
function Class:new(x,y)
local cls = {}
setmetatable(cls, Class)
cls.x = x
cls.y = y
return cls
end
那么最终输出结果将会是我们预期的:
10 20
10 20
通过上述分析,我们可以看到,点号和冒号最主要的区别在于是否包含隐性参数self,使用冒号格式定义或调用函数方法时,Lua会默认把调用者对象隐藏起来了,虽然隐藏起来了,但是我们却不能忽略它的存在性,不管你相信不相信,它就在那里,不左不右。而使用点号格式定义或调用函数方法时,所有参数都是被显示地声明的,不会躲躲藏藏,有多少就是多少,因此,如果我们需要传递调用者对象,那么必须显示声明之。
下面来看几个例子
例1
a = { x = 1 }
function a.fun(self)
print(self.x)
end
a.fun(a) --输出1,将a自己做为参数传给fun函数的self
通过点号格式定义fun,并且通过点号调用函数fun。定义时显示给出self形参用于接收调用者对象;调用时必须显示给出调用者对象作为实参传入。
例2
function a:fun()
print(self.x)
end
a.fun(a)
通过冒号格式定义fun,并且通过点号调用fun。定义时隐藏了形参self,虽然我们看不到,但是self是客观存在的,因此,在函数内部我们可以直接使用self;调用时显示给出调用者对象作为实参传入。
例3
function a:fun()
print(self.x)
end
a:fun()
通过冒号格式定义和调用fun。定义时隐藏了形参self,调用时也隐藏了调用者对象这个实参,虽然我们看不到,但是a这个实参确确实实是被传递给了self。
上面讨论的都是函数方法的定义和调用,那么对于非函数的数据成员又是怎么样的呢?对于数据成员的访问我们是否也是可以通过冒号或点号的形式来完成呢?很遗憾地告诉你,答案是否定的。
看一个例子
girl = {money = 200}
function girl.goToMarket(girl ,someMoney)
girl.money = girl.money - someMoney
end
girl.goToMarket(girl ,100)
print(girl.money)
输出结果
100
girl = {money = 200}
function girl.goToMarket(girl ,someMoney)
girl.money = girl.money - someMoney
end
girl.goToMarket(girl ,100)
print(girl:money)
输出结果
error:function arguments expected near ')'
通过上面例子可以看到,对于非成员函数的数据成员的访问,可以用点号的形式,但是不能用冒号的形式。
综上所述,给出一条不成文的约定:
用lua进行面向对象的编程,成员方法的声明和调用统一用冒号形式,对于数据成员的调用全部用点号形式。
LUA中的冒号、点和self的更多相关文章
- lua 中的点、冒号与self
[lua 中的点.冒号与self] lua编程中,经常遇到函数的定义和调用,有时候用点号调用,有时候用冒号调用. girl = {money = 200} function girl.goToMark ...
- Lua中的点、冒号与self
Lua中的点.冒号与self,它们之间的关系主要体现在函数的定义与调用上,Lua在函数定义时可以用点也可以用冒号,如: function mytable.fun(p) return p end fun ...
- lua中的面向对象编程
简单说说Lua中的面向对象 Lua中的table就是一种对象,看以下一段简单的代码: 上述代码会输出tb1 ~= tb2.说明两个具有相同值得对象是两个不同的对象,同时在Lua中table是引用类型的 ...
- Lua中的一些库(1)
[数学库] 数学库(math)由一组标准的数学函数构成.这里主要介绍几个常用的函数,其它的大家可以自行百度解决. 三角函数(sin,cos,tan……)所有的三角函数都使用弧度单位,可以用函数deg( ...
- <6>Lua元表和冒号 self
Lua中没有像C.C++.JAVA中的类概念,面向对象等 ,但我们可以模拟出来 1. Lua中有个很重要的概念元表 设置元表setmetatable()函数 获取元表getmetatable()函数 ...
- 理解lua中 . : self
前言 在LUA中,经常可以看到:. self,如果你学习过Java或C#语言,可以这样理解 .对于c#和java的静态方法 :相当于是实例方法 今天在CSDN上看到一篇博客写的很清楚,转载过来 原文出 ...
- Lua中“.”调用方法与“:”调用方法的区别
Lua中“.”调用方法与“:”调用方法的区别: ...
- 【转载】Lua中实现类的原理
原文地址 http://wuzhiwei.net/lua_make_class/ 不错,将metatable讲的很透彻,我终于懂了. --------------------------------- ...
- Unity3D热更新之LuaFramework篇[05]--Lua脚本调用c#以及如何在Lua中使用Dotween
在上一篇文章 Unity3D热更新之LuaFramework篇[04]--自定义UI监听方法 中,我对LuaBehaviour脚本进行了扩展,添加了两个新的UI监听方法,也提到最好能单写一个脚本处理此 ...
随机推荐
- C++——函数模板和类模板
声明: //template 关键字告诉C++编译器 我要开始泛型了.你不要随便报错 //数据类型T 参数化数据类型 template <typename T> void myswap(T ...
- 今天工作整整一个月了,来记录一下(web前端)
25号,工作整整一个月了,时光飞逝, 这一个月以来,无论是工作上还是生活上,都让我成长了很多,也多了些对人生的思考… 先回顾一下找工作的那段时间吧年前找工作有多辛酸,年后找工作就有多幸运那段日子,我这 ...
- NX二次开发-UFUN获取当前导出CGM选项设置UF_CGM_ask_session_export_options
文章转载自唐康林NX二次开发论坛,原文出处: http://www.nxopen.cn/thread-126-1-1.html 刚才有同学问到这个问题,如果是用NXOpen来做,直接录制一下就可以了: ...
- NX二次开发-NXOPEN更改工程图视图名字baseView1->SetName("LSY");
NX9+VS2012 #include <uf.h> #include <uf_draw.h> #include <uf_obj.h> #include <u ...
- Spring源码由浅入深系列五 GetBean
获取bean的过程如上图所示.下一章将继续图示讲解createBean的过程.
- 可搭建SS服务上网的不限流量VPS推荐
https://itldc.com/en,7个机房,推荐指数:★★★★ 1995年运作至今,有多个机房,包括:新加坡.洛杉矶.新泽西.立陶宛.乌克兰.保加利亚.荷兰.VPS特征: KVM虚拟(支持BB ...
- Java & 架构硬核福利,速度上车!
极客时间福利时间! 最近,栈长每周都会给大家带来极客时间的专栏拼团优惠,给错过优惠的朋友一个再次优惠上车的机会. <从0开始学架构>和<Java核心技术36讲>,这两个专栏很火 ...
- <Django>博客项目
0.项目的通用流程 项目立项 需求分析 原型 前端 页面设计 UI及交互实现 后端 架构设计 数据库设计 代码模板实现 单元测试 网站整合 功能及集成测试 网站发布 1.BBS项目需求分析 需要哪些表 ...
- git mac安装
1.git安装包安装 去官网下载最行的git版本 安装即可 https://git-scm.com/download/mac 但是一般的git仓库需要sshkey来做验证 下面奉上具体的命令: 需要生 ...
- 多个for循环使用
for循环 例子 语法 vue.js的for循环 <div id="myfor"><li v-for="student in studentList&q ...