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监听方法,也提到最好能单写一个脚本处理此 ...
随机推荐
- Python 爬取12306火车票
获取火车站 stations.py #import certifi #import urllib3 import re import requests from pprint import pprin ...
- sqoop的导入|Hive|Hbase
导入数据(集群为对象) 在Sqoop中“导入”概念指:从非大数据集群(RDBMS)向大数据集群(HDFS,HIVE,HBASE)中传输数据,叫做:导入,即使用import关键字. 1 RDBMS到HD ...
- NX二次开发-UFUN获取工程图详细信息UF_DRAW_ask_drawing_info
NX9+VS2012 #include <uf.h> #include <uf_draw.h> #include <uf_part.h> UF_initialize ...
- 从[id setValue: forKey:]了解KVC
<Objective-C基础教程> P224页有详细介绍 下边是apple官网的简单介绍 和一个应用的例子. KVC就是Key-value coding,大意是允许通过一个Key来读写一个 ...
- Java-Class-C:org.springframework.http.converter.StringHttpMessageConverter
ylbtech-Java-Class-C:org.springframework.http.converter.StringHttpMessageConverter 1.返回顶部 1.1. impor ...
- Java-Class-@I:org.junit.Test
ylbtech-Java-Class-@I:org.junit.Test 1.返回顶部 2.返回顶部 3.返回顶部 4.返回顶部 1. package org.junit; import ...
- LeetCode 182. Duplicate Emails (查找重复的电子邮箱)
题目标签: 题目给了我们一个 email 的table,让我们找到重复的 email. 可以建立 Person a, Person b, 找到两个表格中,emai 相等 但是 id 不同的 email ...
- Go kit 概览
该篇为翻译文:原文地址 https://github.com/go-kit/kit Go kit 是一个语言工具包,用于在GO 语言中构建微服务.我们可以解决分布式系统和应用程序架构中的常见问题,因此 ...
- (转)Python之路,Day6 - 面向对象学习
本节内容: 面向对象编程介绍 为什么要用面向对象进行开发? 面向对象的特性:封装.继承.多态 类.方法. 引子 你现在是一家游戏公司的开发人员,现在需要你开发一款叫做<人狗大战> ...
- spark入门到精通(后续开始学习)
早几年国内外研究者和业界比较关注的是在 Hadoop 平台上的并行化算法设计.然而, HadoopMapReduce 平台由于网络和磁盘读写开销大,难以高效地实现需要大量迭代计算的机器学习并行化算法. ...