一些语言本身是没有面向对象这一说的,类似 lua, js。但是平时使用时,往往会利用语言上的特性来模拟 OO。 初学lua,也看了很多网上的资料、博客,一直不是很理解,只是照猫画虎。现在理解地差不多了,记录一下。

lua 用的是其强大的 table,可以简单地理解为 hash + array。作为 OO,我们需要模仿的有类和对象,每个对象有属性和方法。

首先我们用 table 模拟一个类,这个类有一个 new 的方法,可以生成一个对象,这个对象我们依然使用 table 进行模拟。这里的 new 并不像 c++ 中有特殊的含义,这是一个函数名,可以叫做任何名字,例如 create

除过属性,一个对象还应该拥有方法。

 

这样看上去好像是正常的,但是实际上有点问题,这个问题和 lua 的闭包(捕获局部变量)和优化有关。我理解地不是很透彻,我就不解释详细解释原因了,因为这里也不会用这种方法模拟,我只是想说明这种是可行的,解决方法也很简单直接,只要在 obj 前加上 local 即可。

如果没有加 local 的话,你生成两个对象,然后把函数打印出来,会发现两个对象拥有的函数是同一个函数,听起来还不错,sayHi 的表现也是正常的,但是你同时会发现,show 函数中的 obj 绑定的也就会是最后一次生成的对象,这显然不是我们想要的结果。当然这要在 obj 前边加上 local 就能解决了。

但是加上 local 后,出现了另一个问题,那就是所有的函数对每个对象来说都有一份,这实际上是很浪费的。学过 c++ 大家都知道,c++ 中的类函数实际上只有在类中有一份,所有的对象调用的都是这一个函数,然后通过一个隐式的 this 指针来进行数据的调用。

在 lua 里,我们可以利用 metatable(元表)来进行模拟。不清楚 metatable 的可以先去看一下教程。这里,我们让‘类’作为所有‘对象’的 metatable,将函数定义在‘类’中,这样所有对象在调用函数时,都会前往‘类’中调用。

 

这里我们就基本地模拟了面向对象。不过每次都要显式指定十分麻烦,lua 中有一个语法糖可以提供我们使用。

obj.func(obj) <=> obj:func()
使用冒号时,会隐式地将调用者传递进去(体现为 self,类似于 c++ 中的 this),我们修正一下

 

这里我以前最疑惑的就是上边那个 self 了,这个 self 在两个函数里边实际上是不同的。

最后,这里是我的一个记录,如果可能的话,希望能帮到一些人。如果有人发现文章中的错误,还望指出。

最近在做codewars上面的Haskell题,经常会碰到一些类型之间转换的问题。因为Haskell是强类型,不允许隐式类型转换,作为新手着实有点头疼,中文的Haskell资料又比较少,我整理了一下常用的几种转换方式。(P.S. 英文好的可以直接去看Haskell Wiki)

还有因为我也是新手,在表述方面可能会有一些错误的地方,如果有人发现我的不正确的表述,还望指出。

继续阅读

最近想学 haskell,不过每次拿起来都是认认真真看了前一部分,觉得信心大增,网上找些习题,却发现一道都做不了。不了了之,然后就等下一次再有动力的时候,又从头开始。

继续阅读

觉得作为一个队,就应该为队里留点什么,所以想搭一个关于 acm 的队里 wiki。虽然说我觉得标记语言不错,但不是所有人愿意花这个时间,所以还是给装上一个可视化编辑器吧。于是……

一大堆问题就来了

继续阅读