17.2 关联对象属性 |
weak tables的另一个重要的应用就是和对象的属性关联。在一个对象上加入更多的属性是无时无刻都会发生的: 函数名称,tables的缺省值,数组的大小,等等。
当对象是表的时候,我们可以使用一个合适的唯一key来将属性保存在表中。就像我们在前面说的那样,一个很简单并且可以防止错误的方法是建立一个新的对象(典型的比如table)然后把它当成key使用。然而,如果对象不是table,它就不能自己保存自身的属性。即使是tables,有些时候我们可能也不想把属性保存在原来的对象中去。例如,我们可能希望将属性作为私有的,或者我们不想在访问table中元素的时候受到这个额外的属性的干扰。在上述这些情况下,我们需要一个替代的方法来将属性和对象联系起来。当然,一个外部的table提供了一种理想化的方式来联系属性和对象(tables有时被称作联合数组并不偶然)。我们把这个对象当作key来使用,他们的属性作为vaule。一个外部的table可以保存任何类型对象的属性(就像Lua允许我们将任何对象看作key)。此外,保存在一个外部table的属性不会妨碍到其他的对象,并且可以像这个table本身一样私有化。
然而,这个看起来完美的解决方案有一个巨大的缺点:一旦我们在一个table中将一个对象使用为key,我们就将这个对象锁定为永久存在。Lua不能收集一个正在被当作key使用的对象。如果我们使用一个普通的table来关联函数和名字,那么所有的这些函数将永远不会被收集。正如你所想的那样,我们可以通过使用weak table来解决这个问题。这一次,我们需要weak keys。一旦没有其他地方的引用,weak keys并不会阻止任何的key被收集。从另一方面说,这个table不会存在weak vaules;否则,活动对象的属性就可能被收集了。
Lua本身使用这种技术来保存数组的大小。像我们下面即将看到的那样,table库提供了一个函数来设定数组的大小,另一个函数来读取数组的大小。当你设定了一个数组的大小,Lua 将这个尺寸保存在一个私有的weak table,索引就是数组本身,而value就是它的尺寸。