因为Redis要用到Lua脚本,就去浏览了一遍Lua语法,这里记录一下对协同程序和面向对象的理解。

协同程序(coroutine)

看起来很像Go的协程(goroutine),但是其实不是一回事。

Go的协程与Lua协同程序的主要区别在于,一个具有多个Go协程的程序可以同时运行多个Goroutine的,而协同程序却需要彼此协作的运行。

注意以下两点:

  1. 任一指定时刻,只有一个协同程序正在运行
  2. 正在运行的协同程序只有在明确的被要求挂起的时候才会被挂起。

这意味着,其实Lua还是单线程(或者说同步的)执行程序。

 

这里以生产者消费者模式举例。Ps.我加了很多print用于观察

productor() 就是生产者函数, consumer() 就是消费者函数。

生产者函数负责Send数据, 消费者函数负责Receive数据。

Send本质其实是挂起协同程序(coroutine.yield),将值传递出去。

Receive本质是唤醒协同程序(coroutine.resume),接受数据值。

 

所以实际上程序的整体执行顺序如下,

  1. 创建生产者协同程序
  2. 调用消费者函数consumer
  3. consumer调用Receive函数
  4. Receive函数唤醒协同程序productor
  5. 协同程序productor调用Send函数,挂起函数yield发送数据
  6. Received函数接收到值后,返回给消费者函数consumer
  7. 消费者函数打印输出值,再次调用Received函数
  8. 再次唤醒协同程序…注意!!!上次我们的协同程序运行到了print(“离开 Send”)这一行代码的前一行。

 

最终打印输出内容:

 

能够对的上…嗯,就是这么个意思。

 

面向对象

面向对象三大特性:

  • 封装:指能够把一个实体的信息、功能、响应都装入一个单独的对象中的特性。
  • 继承:继承的方法允许在不改动原程序的基础上对其进行扩充,这样使得原功能得以保存,而新功能也得以扩展。这有利于减少重复编码,提高软件的开发效率。
  • 多态:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。

 

对象一般由属性和方法组成,在Lua中可以用table来表示属性,用function表示方法。

继承的话,跟元表matetable看起来很像。

 

咱们直接上实例吧,这段代码是来自于菜鸟教程,但是做了一些修改。

 

这里做一些讲解。

lua的函数是可以 “.”(点号) 或者 “:” (冒号)调用的,它们的区别就是冒号调用省略了第一个参数self。

比如我们可以仅修改Shape:new 函数为 Shape.new(Shape, …),这种情况下还是可以正常调用的。

 

第二是对new函数做讲解。

Rectangle是Shape的一个子类,我们来看看它的new方法Rectangle:new。

首先o是传入的参数,一般是nil,那么会取为Rectangle的基类Shape。

然后将self(也就是我们的Rectangle对象)设置为 o 的元表。

这种情况下,我们回忆下元表的规则:

  • setmetatable(table,metatable): 对指定 table 设置元表(metatable),如果元表(metatable)中存在 __metatable 键值,setmetatable 会失败。
  • getmetatable(table): 返回对象的元表(metatable)。

所以我们将Rectangle设置为0的元表,将o的元表Rectangle的__index元方法设置为Rectangle自己。

Lua的元表查询规则:表中没有去元表的__index查找,元表中没有就去元表的元表…这样就实现了继承。

然后我们对o的area属性赋值,在菜鸟教程中,这个值是给了元表,但是这样是不合理的。具体的你创建两个对象,传递不同的参数进去,试试就明白了。

 

嗯,以上是我对Lua的协同程序,面向对象的理解…没了。

【Lua】协同程序 与 面向对象
Tagged on:
0 0 vote
Article Rating
订阅
提醒
0 评论
Inline Feedbacks
View all comments