在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的更多相关文章

  1. lua 中的点、冒号与self

    [lua 中的点.冒号与self] lua编程中,经常遇到函数的定义和调用,有时候用点号调用,有时候用冒号调用. girl = {money = 200} function girl.goToMark ...

  2. Lua中的点、冒号与self

    Lua中的点.冒号与self,它们之间的关系主要体现在函数的定义与调用上,Lua在函数定义时可以用点也可以用冒号,如: function mytable.fun(p) return p end fun ...

  3. lua中的面向对象编程

    简单说说Lua中的面向对象 Lua中的table就是一种对象,看以下一段简单的代码: 上述代码会输出tb1 ~= tb2.说明两个具有相同值得对象是两个不同的对象,同时在Lua中table是引用类型的 ...

  4. Lua中的一些库(1)

    [数学库] 数学库(math)由一组标准的数学函数构成.这里主要介绍几个常用的函数,其它的大家可以自行百度解决. 三角函数(sin,cos,tan……)所有的三角函数都使用弧度单位,可以用函数deg( ...

  5. <6>Lua元表和冒号 self

    Lua中没有像C.C++.JAVA中的类概念,面向对象等 ,但我们可以模拟出来 1. Lua中有个很重要的概念元表 设置元表setmetatable()函数  获取元表getmetatable()函数 ...

  6. 理解lua中 . : self

    前言 在LUA中,经常可以看到:. self,如果你学习过Java或C#语言,可以这样理解 .对于c#和java的静态方法 :相当于是实例方法 今天在CSDN上看到一篇博客写的很清楚,转载过来 原文出 ...

  7. Lua中“.”调用方法与“:”调用方法的区别

    Lua中“.”调用方法与“:”调用方法的区别:                                                                             ...

  8. 【转载】Lua中实现类的原理

    原文地址 http://wuzhiwei.net/lua_make_class/ 不错,将metatable讲的很透彻,我终于懂了. --------------------------------- ...

  9. Unity3D热更新之LuaFramework篇[05]--Lua脚本调用c#以及如何在Lua中使用Dotween

    在上一篇文章 Unity3D热更新之LuaFramework篇[04]--自定义UI监听方法 中,我对LuaBehaviour脚本进行了扩展,添加了两个新的UI监听方法,也提到最好能单写一个脚本处理此 ...

随机推荐

  1. 如何理解Vue的render函数

    第一个参数(必须) - {String | Object | Function} <!DOCTYPE html> <html lang="en"> < ...

  2. [转]mysql主从同步

    Mysql镜像机制配置过程主服务器:   192.168.0.25从服务器:   192.168.0.26MYSQL版本:mysql-5.0.22.tar.gz安装日期:2010年5月14日  一.镜 ...

  3. 3.7.4 Tri0 and tri1 nets

    Frm: IEEE Std 1364™-2001, IEEE Standard Verilog® Hardware Description Language The tri0 and tri1 net ...

  4. org.apache.hadoop.hbase.PleaseHoldException: Master is initializing

    电脑换了重新装了下系统,在本机ubuntu 的环境下搭建hadoopCDH4.5 伪分布式.进入Hbase shell,在创建表的时候出现异常如下: ERROR: org.apache.hadoop. ...

  5. 使用python和tushare查询股票历史名称变更记录

    接口:namechange 描述:历史名称变更记录 注:tushare库下载和初始化教程,请查阅我之前的文章 输入参数 名称       |       类型       |       必选    ...

  6. 第一周课堂笔记1th

    1.      计算机基本组成 CPU:中央处理器,人的大脑 内存:临时存储数据       (特点:断电即消失,容量小12G 24G) 硬盘:永久存储数据(特点:断电不消失容量大,500G 1T) ...

  7. <mysql>mysql基础学习

    1.Join语法 JOIN 按照功能大致分为如下三类: INNER JOIN(内连接,或等值连接):取得两个表中存在连接匹配关系的记录. LEFT JOIN(左连接):取得左表(table1)完全记录 ...

  8. LA2218 Triathlon /// 半平面交 oj22648

    题目大意: 铁人三项分连续三段:游泳 自行车 赛跑 已知各选手在每个单项中的速度v[i],u[i],w[i] 设计每个单项的长度 可以让某个特定的选手获胜 判断哪些选手有可能获得冠军 输出n行 有可能 ...

  9. 使用kubeadm安装kubernetes 1.15

    1.主机准备篇 使用vmware Workstation 10创建一台虚拟机,配置为2C/2G/50G,操作系统为CentOS Linux release 7.6.1810 (Core). IP地址为 ...

  10. C++ static静态成员变量在类中仅仅是声明

    今天写代码时看到: 图1的3个静态成员变量在类中仅仅是声明,没有定义以及分配内存:必须在类外,图中就是cpp中,定义分配内存,才能使用