首先,先来一段在lua创建一个类与对象的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Class = {}
Class.__index = Class
 
function Class:new(x,y)
    local temp = {}
    setmetatable(temp, Class)
    temp.x = x
    temp.y = y
    return temp
end
 
function Class:test()
    print(self.x,self.y)
end
 
 
object = Class.new(10,20)
 
object:test()

猜一下会输出什么结果呢?

输出:

>lua -e "io.stdout:setvbuf 'no'" "object.lua" 
20    nil
>Exit code: 0

我们的y值怎么没了?

这个原因很简单,因为我们创建一个对象的时候使用了一个 . 号

在lua程序设计第二版中,有提到当一项操作所作用的”接受者”,需要一个额外的参数来表示该接受者,这个参数通常称为self或this

然后我们在这段代码加上 self

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Class = {}
Class.__index = Class
 
function Class:new(x,y)
    local temp = {}
    setmetatable(temp, Class)
    temp.x = x
    temp.y = y
    return temp
end
 
function Class:test()
    print(self.x,self.y)
end
 
 
object = Class.new(self,10,20)
 
object:test()

然后我们在看一下输出

>lua -e "io.stdout:setvbuf 'no'" "object.lua" 
10    20
>Exit code: 0

这下就正常了!!嗯,每次创建一个对象的时候都有写一个self,会不会感觉很麻烦呢?lua提供了用冒号的方式在一个方法定义中添加一个额外的参数,以及在一个方法调用中添加一个额外的实参

然后代码改成

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Class = {}
Class.__index = Class
 
function Class:new(x,y)
    local temp = {}
    setmetatable(temp, Class)
    temp.x = x
    temp.y = y
    return temp
end
 
function Class:test()
    print(self.x,self.y)
end
 
 
object = Class:new(10,20)
 
object:test()

输出正常:

>lua -e "io.stdout:setvbuf 'no'" "object.lua" 
10    20
>Exit code: 0

如果,就这么完的话,本来是一件很欢乐的事情,但是,我尝试了一下以下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Class = {}
Class.__index = Class
 
function Class.new(x,y)
    local temp = {}
    setmetatable(temp, Class)
    temp.x = x
    temp.y = y
    return temp
end
 
function Class:test()
    print(self.x,self.y)
end
 
 
object = Class.new(10,20)
 
object:test()

出乎意料的是:

>lua -e "io.stdout:setvbuf 'no'" "object.lua" 
10    20
>Exit code: 0

代码正常运行….这个让人很费解,本来,点号对方法的操作是需要一个额外的接受者,第一段代码已经说明了这个问题,但是,现在程序有正常运行,令我真是有点费解…

然后,我接着尝试又发现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Class = {}
Class.__index = Class
 
function Class.new(x,y)
    local temp = {}
    setmetatable(temp, Class)
    temp.x = x
    temp.y = y
    return temp
end
 
function Class:test()
    print(self.x,self.y)
end
 
 
object = Class:new(10,20)
 
object:test()

输出结果:

>lua -e "io.stdout:setvbuf 'no'" "object.lua" 
table: 003CACA0    10
>Exit code: 0

这个只不过跟第一段代码点号和冒号的位置调换了一下,就出现了这样的结果…

如果,你仔细想想,这里和第一段代码的区别,可以发现,其实,这里就可以证明了冒号其实就是默认传了一个实参到方法中

为了证明冒号的作用,我改动了一下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Class = {}
Class.__index = Class
 
function Class:new(x,y)
    local temp = {}
    setmetatable(temp, Class)
    temp.x = x
    temp.y = y
    return temp
end
 
function Class.test()
    print(self.x,self.y)
end
 
 
object = Class:new(10,20)
 
object:test()

输出的结果是:

>lua -e "io.stdout:setvbuf 'no'" "object.lua" 
lua: object.lua:15: attempt to index global 'self' (a nil value)
stack traceback:
    object.lua:15: in function 'test'
    object.lua:21: in main chunk
    [C]: ?
>Exit code: 1

从这里的错误可以看出,没有self这个参数,竟然,方法用的是点号,那我们试一下把对象传进去看下能不能正常运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Class = {}
Class.__index = Class
 
function Class:new(x,y)
    local temp = {}
    setmetatable(temp, Class)
    temp.x = x
    temp.y = y
    return temp
end
 
function Class.test()
    print(self.x,self.y)
end
 
 
object = Class:new(10,20)
 
object:test(object)

遗憾的是这样的改动是错误的,错误的结果也是一样的

>lua -e "io.stdout:setvbuf 'no'" "object.lua" 
lua: object.lua:15: attempt to index global 'self' (a nil value)
stack traceback:
    object.lua:15: in function 'test'
    object.lua:21: in main chunk
    [C]: ?
>Exit code: 1

那我们这次尝试下想刚才那样,把方法的点号搞成一致看下效果怎样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Class = {}
Class.__index = Class
 
function Class:new(x,y)
    local temp = {}
    setmetatable(temp, Class)
    temp.x = x
    temp.y = y
    return temp
end
 
function Class.test()
    print(self.x,self.y)
end
 
 
object = Class:new(10,20)
 
object.test()

遗憾的是跟之前不一样,还是不能运行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Class = {}
Class.__index = Class
 
function Class:new(x,y)
    local temp = {}
    setmetatable(temp, Class)
    temp.x = x
    temp.y = y
    return temp
end
 
function Class.test()
    print(self.x,self.y)
end
 
 
object = Class:new(10,20)
 
object.test()
1
  
1
回想一下,冒号的作用可以传递一个实参,对于方法的操作我们需要一个接受者,那么进行以下的改动
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Class = {}
Class.__index = Class
 
function Class:new(x,y)
    local temp = {}
    setmetatable(temp, Class)
    temp.x = x
    temp.y = y
    return temp
end
 
function Class:test()
    print(self.x,self.y)
end
 
 
object = Class:new(10,20)
 
object.test(object)

这次输出就正常了

>lua -e "io.stdout:setvbuf 'no'" "object.lua" 
10    20
>Exit code: 0

这段代码告诉了我们,想要操作一个方法就一定需要一个额外参数来表示该值,对于点号,我们必须显示传递一个实参,才能使程序正常运行,而为了方便,我们可以直接使用冒号来简化操作.

lua冒号点号

在lua开发中我们经常会混淆这两者之间的区别,下面通过一个示例来解释:

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()
-- 等价于
object.test(object)

可以看到: 
1、 定义的时候: Class:test()与 Class.test(self)是等价的 ,点号(.)要达到冒号(:)的效果要加一个self参数到第一个参数; 
2、 调用的时候: object:test() 与object.test(object)等价 ,点号(.)要添加对象自身到第一个参数。

总结:可以把点号(.)作为静态方法来看待,冒号(:)作为成员方法来看待。

结论:

罗嗦了半天其实,可以用一下一句话来避免这个问题:

用lua进行面向对象的编程,声明方法和调用方法统一用冒号,对于属性的调用全部用点号

lua面向对象编程之点号与冒号的差异详细比较的更多相关文章

  1. [转]lua面向对象编程之点号与冒号的差异详细比较

    首先,先来一段在lua创建一个类与对象的代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Class = {} Class.__index = Cl ...

  2. Lua中调用函数使用点号和冒号的区别

    1.初学者最易混乱Top1——调用函数时用点号还是用冒号? 我们来看看下面的两句代码: mSprite.setPosition(, ); mSprite:setPosition(, ); 对于初次接触 ...

  3. 理解lua 语言中的点、冒号与self

    转载自: http://blog.csdn.net/wangbin_jxust/article/details/12170233 lua编程中,经常遇到函数的定义和调用,有时候用点号调用,有时候用冒号 ...

  4. PHP面向对象编程之深入理解方法重载与方法覆盖(多态)

    这篇文章主要介绍了PHP面向对象编程之深入理解方法重载与方法覆盖(多态)的相关资料,需要的朋友可以参考下: 什么是多态? 多态(Polymorphism)按字面的意思就是"多种状态" ...

  5. 深入理解JavaScript系列(17):面向对象编程之概论

    介绍 在本篇文章,我们考虑在ECMAScript中的面向对象编程的各个方面(虽然以前在许多文章中已经讨论过这个话题).我们将更多地从理论方面看这些问题. 特别是,我们会考虑对象的创建算法,对象(包括基 ...

  6. python基础-面向对象编程之继承

    面向对象编程之继承 继承的定义:是一种新建类的方式,新建的类称之为子类或派生类,被继承的父类称之为基类或超类 继承的作用:子类会""遗传"父类的属性,从而解决代码重用问题 ...

  7. python基础-面向对象编程之封装、访问限制机制和property

    面向对象编程之封装 封装 定义:将属性和方法一股脑的封装到对象中,使对象可通过"对象."的方式获取或存储数据. 作用:让对象有了"."的机制,存取数据更加方便 ...

  8. python基础-面向对象编程之反射

    面向对象编程之反射 反射 定义:通过字符串对对象的属性和方法进行操作. 反射有4个方法,都是python内置的,分别是: hasattr(obj,name:str) 通过"字符串" ...

  9. python基础-面向对象编程之多态

    面向对象编程之多态以及继承.抽象类和鸭子类型三种表现形式 多态 定义:同一种类型的事物,不同的形态 作用: 多态也称之为"多态性".用于在不知道对象具体类型的情况下,统一对象调用方 ...

随机推荐

  1. android应用Theme(二)

    另外一种实现android应用Theme的方式是通过apk来实现的. 以下是一个demo. 1.首先必须新建一个apk.类似的插件,然后在该apk的AndroidManifest.xml文件的appl ...

  2. \u Unicode和汉字转化

    介绍 \uxxxx这种格式是Unicode写法,表示一个字符,其中xxxx表示一个16进制数字,范围所0-65535. Unicode十六进制数只能包含数字0-9.大写字母A-F或者小写字母A-F.需 ...

  3. C# sqlserver 2008 连接字符串

    sqlserver 2008 的连接字符串和sql2005的几乎是一样的,但是,他们对于其中的一些配置要求不同.我试着用了很多连接字符串,最后找到了问题的原因,特别记录到这里,如果有相同问题的同学,可 ...

  4. [转载]eclipse自动同步插件filesync的使用

    原文地址:eclipse自动同步插件filesync的使用作者:老孙丢了金箍棒    这篇文章和之前我写的<eclipse下自动部署WEB项目>根本目的是一样的,只是达到目的的方式不同. ...

  5. iOS获取ipa素材、提取ipa资源图片文件

    当我们看到一款优秀的App时,我们可能对它的一些素材比较感兴趣,或者我们也想仿写一款类似app,那么怎么能获取到它的素材资源文件呢? 下面我以ofo举例: 1.打开iTunes,搜索ofo关键字,选择 ...

  6. mysql--SQL编程(关于mysql中的日期,实例,判断生日是否为闰年) 学习笔记2.1

    关于日期处理的实例: 从mysql给出的 example 这个是官方源码下载以及导入,http://dev.mysql.com/doc/employee/en/employees-installati ...

  7. 自动化部署必备技能—定制化RPM包[转载]

    回顾下安装软件的三种方式: 1.编译安装软件,优点是可以定制化安装目录.按需开启功能等,缺点是需要查找并实验出适合的编译参数,诸如MySQL之类的软件编译耗时过长. 2.yum安装软件,优点是全自动化 ...

  8. 详解PV、UV、VV、IP及其关系与计算

    一.什么是PV? PV即Page View,网站浏览量,指页面浏览的次数,用以衡量网站用户访问的网页数量.用户每次打开一个页面便记录1次PV,多次打开同一页面则浏览量累计.一般来说,PV与来访者的数量 ...

  9. php性能分析工具xhprof

    安装方法: wget http://pecl.php.net/get/xhprof-0.9.x.tgz cp xhprof-0.9.x.tgz /home/www/xhprof.tgz tar zxv ...

  10. PCM、G.729等常用VoIP编码的理论带宽计算

    可能通信背景的同学,一提到PCM编码,脑海里都能跳出来一个数值64K. 一.64KB还是64Kb? 64Kb! 二.哪里来的64Kb? CCITT规定抽样率为每秒8000KHz,每抽样值编8位码,所以 ...