博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
lua面向对象编程之点号与冒号的差异详细比较
阅读量:6709 次
发布时间:2019-06-25

本文共 5076 字,大约阅读时间需要 16 分钟。

首先,先来一段在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进行面向对象的编程,声明方法和调用方法统一用冒号,对于属性的调用全部用点号

转载地址:http://cialo.baihongyu.com/

你可能感兴趣的文章
In FontFamilyFont, unable to find attribute android:font的报错处理
查看>>
网络编程-I/O基础
查看>>
Netty+SpringBoot+FastDFS+Html5实现聊天App详解(一)
查看>>
【跃迁之路】【721天】程序员高效学习方法论探索系列(实验阶段478-2019.2.11)...
查看>>
区块链之比特币的潜在激励
查看>>
Learning Python, 5th Edition 读书笔记 1
查看>>
【译】理解回调和Promise
查看>>
市场变冷,不要灰心。更应该延长你的黄金岁月
查看>>
又一轮子?Typescript+React+Redux,放弃saga,支持服务器渲染同构
查看>>
一起再看执行上下文/作用域链/原型链
查看>>
区块链是一种用一种不可变的形式存储数字信息
查看>>
【须弥SUMERU】宜信分布式安全服务编排实践
查看>>
docker笔记2-镜像与容器
查看>>
Node.js this指针指向module.exports、global、实例,指针显式、隐式传递与绑定与优先级...
查看>>
H5以及Node读取excel
查看>>
Nginx基础篇(1)- Nginx的快速搭建和基本参数
查看>>
opencv python K-Means聚类
查看>>
从DevOps到AIOps,阿里如何实现智能化运维?
查看>>
Vue中的RouteMock实现思路及其问题
查看>>
前端每日实战:25# 视频演示如何用纯 CSS 创作一个慧星拖尾效果的 loader 动画...
查看>>