第一版是为 Lua 5.0 编写的。虽然在很大程度上仍然适用于后续版本,但有一些差异。
第四版针对 Lua 5.3,可在 亚马逊 和其他书店购买。
购买本书,您还可以帮助支持 Lua 项目。
用 Lua 编程 | ||
第二部分。表和对象 第 16 章。面向对象编程 |
许多人认为隐私是面向对象语言不可或缺的一部分;每个对象的状态应该是其自己的内部事务。在某些面向对象语言(如 C++ 和 Java)中,您可以控制对象字段(也称为实例变量)或方法是否在对象外部可见。其他语言(如 Smalltalk)使所有变量为私有,所有方法为公有。第一种面向对象语言 Simula 没有提供任何类型的保护。
我们之前展示过的 Lua 中对象的主要设计不提供隐私机制。部分原因是,我们使用通用结构(表)来表示对象。但这还反映了 Lua 背后的一些基本设计决策。Lua 并非用于构建大型程序,在大型程序中,许多程序员会参与很长时间。恰恰相反,Lua 针对中小型程序,通常是更大系统的一部分,通常由一个或几个程序员甚至非程序员开发。因此,Lua 避免了过多的冗余和人为限制。如果您不想访问对象内部的某个内容,只需不访问即可。
然而,Lua 的另一个目标是灵活,为程序员提供元机制,通过该机制她可以模拟许多不同的机制。尽管 Lua 中对象的基本设计不提供隐私机制,但我们可以以不同的方式实现对象,以便进行访问控制。虽然这种实现并不经常使用,但了解它很有帮助,既因为它探索了 Lua 的一些有趣之处,又因为它可以为其他问题提供一个好的解决方案。
这种替代设计的基本思想是通过两张表来表示每个对象:一张用于其状态;另一张用于其操作,或其接口。对象本身是通过第二张表访问的,即通过构成其接口的操作访问的。为了避免未经授权的访问,表示对象状态的表不会保存在另一张表的字段中;相反,它只保存在方法的闭包中。例如,为了用这种设计表示我们的银行账户,我们可以创建一个新对象,运行以下工厂函数
function newAccount (initialBalance) local self = {balance = initialBalance} local withdraw = function (v) self.balance = self.balance - v end local deposit = function (v) self.balance = self.balance + v end local getBalance = function () return self.balance end return { withdraw = withdraw, deposit = deposit, getBalance = getBalance } end首先,该函数创建一个表来保存内部对象状态,并将其存储在局部变量
self
中。然后,该函数为对象的每个方法创建一个闭包(即嵌套函数的实例)。最后,该函数创建并返回外部对象,该对象将方法名称映射到实际的方法实现。这里关键的一点是,这些方法不会将self
作为额外的参数获取;相反,它们直接访问self
。因为没有额外的参数,所以我们不使用冒号语法来操作此类对象。方法的调用就像任何其他函数一样
acc1 = newAccount(100.00) acc1.withdraw(40.00) print(acc1.getBalance()) --> 60
这种设计为存储在self
表中的任何内容提供了完全的隐私。在newAccount
返回后,无法直接访问该表。我们只能通过在newAccount
中创建的函数访问它。虽然我们的示例只将一个实例变量放入私有表中,但我们可以将对象的私有部分存储在该表中。我们还可以定义私有方法:它们就像公有方法,但我们不会将它们放入接口中。例如,我们的账户可能会为余额超过一定限额的用户提供 10% 的额外信用,但我们不希望用户访问此计算的详细信息。我们可以按如下方式实现此功能
function newAccount (initialBalance) local self = { balance = initialBalance, LIM = 10000.00, } local extra = function () if self.balance > self.LIM then return self.balance*0.10 else return 0 end end local getBalance = function () return self.balance + self.extra() end ...同样,任何用户都无法直接访问
extra
函数。
版权所有 © 2003–2004 Roberto Ierusalimschy。保留所有权利。 |