Lua的面向对象设计1

18 篇文章 16 订阅
这几天看了Lua程序设计,读懂面向对象设计后,发现真的好巧妙.Lua本身没有支持面向对象的特性,如像C++,java有class等关键字,Lua的面向对象完全是基于其自身的特性来模拟设计的,读懂之后不得不叹服.
Lua的面向对象特性是基于其表和元表的特性来完成的,下面举例说明
比如,我们要设计一个账户类,包含存钱(deposit())取钱(withdraw())的方法,还有余额(balance)成员变量,还有构造实例的方法,如果是C++就好办了:
class Account {
public:
    Account() {"construct...";}
}
无奈脚本语言比较简单,不支持类的概念,只好自己想办法.我们先模拟构造的方法,设为new,我们可以给Account添加一个函数new:
function Account.new()
    end
声明类的目的是可以生成多个类的实例a1,a2,a3...,而且这些实例之间的数据没有联系,也就是说操作a1的数据不能影响到a2,他们只能调用共同的方法.勉为其难,我们先这样试试看:
a1 = Account.new()
a2 = Account.new()
要想生成不同的实例,恐怕还不行.我们知道Lua的表是可以包罗万象的,什么东西都可以往表里面塞:
s = {a = 1, b = 2, "1", 3.3,4.5}
    print(s.a) => 1
    print(s.b) => 2
    print(s[1]) => 1
    print(s[2]) => 3.3
构造时可以利用表来构造:
a1 = Account.new({balance = 10})
a2 = Account.new({balance = 20})
构造函数得变成这样:
function Account.new (obj)
       return obj
    end
好了,我们再设计成员函数deposit
function Account.deposit(v)
        balance = balance + v
    end
调用:
a1 = Account.new({balance = 0}) --余额初始值0
a1.deposit(100) --存100块钱
看看我们能不能实现类的目的.
保存,运行,~~~~(>_<)~~~~运行出错,a1没有deposit成员,确实a1只有balance成员,那我们怎能让其有deposit()方法呢?上面deposit是在Account表里,能够让a1访问到Account的deposit()就达到目的了.对了,通过元表就可以做到:setmetatable(a1, Account),具体说明请看这篇文章,说的很透彻,感谢分享:
改写构造函数之前,我们再探讨成员函数.在C++/java里面
Account a1(0), a2(0);
a1.deposit(100)
然后a1.balance变为100了,a2的balance仍然为0,我们知道类只共享成员函数,不共享成员变量(类静态变量除外),实际上,上面的调用为Account::deposit(&a1),Account为作用域.在Lua里面调用a1.deposit(10)实际上不会改变a1表里面的任何东西,a1仅仅是一个作用域而已,所以要想改变,只能这样:
function Account.deposit(a, v)
        a.balance = a.balance + v
    end
    a1.deposit(a1, 10)
是不是看起来怪怪的,还好Lua为我们提供了语法糖,可以直接类似C++/java里调用成员函数
a1:deposit(10)
不过要这样定义:
function Account:deposit(v)
        self.balance = self.balance + v
    end
这样调用:
a1:deposit(10) =>a1.deposit(a1, 10)
这里的self.balance代表了调用者的balance,即a1调用就a1.balance
这里有个疑问:self不是关键字,它是怎么做到的,self究竟是什么?还望大神告知.
综上,构造函数应该这样写:
function Account:new (obj)
        obj = obj or {}
        setmetatable(obj, self)
        self.__index = self
        return obj
    end
产生一个实例:
a1 = Account:new({balance = 0})
a1:deposit(100)
再次分析一下a1是怎么做到改变其balance的:
a1本身没有deposit成员,继续查找其元表,构造函数设置了元表为Account,故调用Account的deposit()然后self.balance就是a1的balance,从而实现调用.
所以,Lua本身不支持面向对象设计,但是可以通过其特性来模拟,设计确实巧妙.面向对象远远不止这些,后续将继续剖析继承,访问权限等等.






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值