类与方法 |
|
表可以作为关联数组使用。这种功能允许我们将函数存储在类表中,即函数名映射到函数。
A = {}
function A:add(x,y)
return x+y
end
print( A:add(1,2) ) -- prints 3
可以通过使用 Lua 的标签方法来创建类的多个实例。标签方法可用于将函数请求从类实例重定向到类函数表。也就是说,我们不再需要将所有类函数复制到类的每个实例中。例如:
-- settag() returns a table "{}" which has been tagged with a new tag value A = settag({},newtag()) -- use the index tag method to redirect a request for a function to the -- class function table settagmethod(tag(A),"index", function(t,f) return %A[f] end) function A:new(x,y) -- create an instance of class A local t = {x=x,y=y} settag(t,tag(A)) -- tag the new table to tell it what its class type is return t end function A:add() print (self.x+self.y) end function A:sum(a) assert(tag(self)==tag(a)) -- check they are same class print (self.x+a.x,self.y+a.y) end a = A:new(7,9) -- new instance of A a:add() b = A:new(2,4) -- new instance of A b:add() a:sum(b) -- "sum" of 2 instances
settagmethod(tag(A),"index", function(t,f) return rawget(%A,f) end)
a.number = 123
a:number() -- try and call x
a.sum = 7 print( a.sum ) -- should this print <function> or 7 ? (it prints 7)
这个问题无法解决,因为调用请求没有告知标签方法需要哪种类型。我们可以设置一个偏好,例如,类实例值优先于函数表值。(这样做可以支持函数重载。)
如果函数表优先,我们可以使用gettable标签方法,首先检查函数表 `A` 中是否存在该方法,例如:
settagmethod(tag(A), "gettable", function(t,k) if rawget(%A,k) then return rawget(%A,k) else return rawget(t,k) end end )
统一方法:这个问题在 Edgar Toernig 的 Lua 分支 *Sol* 中得到了解决,通过引入统一方法。在这里,函数/方法表与一个标签相关联。当发生表查找时,取决于查找是如何调用的。也就是说,`a.foo` 和 `a:foo` 有不同的含义。`a.foo` 查找名为“foo”的成员,而 `a:foo` 在标记的函数表中查找名为“foo”的方法。因此,您可以拥有两个成员,一个是数据,一个是函数,它们可以和谐地共存,没有冲突。