[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: About the example in "Object-Oriented Programming" on http://www.lua.org/pil/16.1.html
- From: Philipp Janda <siffiejoe@...>
- Date: Tue, 23 Apr 2013 18:17:22 +0200
Am 23.04.2013 16:53 schröbte xinlei fan:
hi
Hi!
I am a freshman in lua programming,and I worked with Javascript for several
years
when I write a simple game framework using lua , I read the article on on
http://www.lua.org/pil/16.1.html,the thoughts much like the prototype,but I
noticed a code fragment
function Account:new (o)
o = o or {} -- create object if user does not provide one
setmetatable(o, self)
self.__index = self
return o
end
I think "self.__index = self" is not make sense,it will lead to a
"prototype circle",
This is a common hack to save some memory. I'm quite surprised that this
issue doesn't come up more often, so I will try to give a detailed
explanation:
Logically there are three tables involved: The object table (`ot` from
now on), the metatable (`mt`) and the index table (`it`).
Let's assume those tables have the following contents (in pseudo-Lua):
ot = {}
mt = {
__index = ..., --> `it`
}
it = {
field1 = 1,
}
and `ot` has `mt` as its metatable.
If one accesses `ot.field1`, Lua checks whether `ot` has a field named
`field1`. It doesn't, so Lua checks whether `ot` has a metatable. It
does, so Lua loads this metatable `mt` and checks for an `__index`
field. There is an `__index` field in `mt` which points to `it`, so Lua
accesses the field `field1` in `it` and returns its value.
As all useful fields in a metatable start with two underscores, and the
fields in a common index table do *not* start with underscores, one can
actually merge `mt` and `it` into one table without conflict (let's call
it hack table `ht`).
ot = {}
ht = {
__index = ..., --> `ht`
field1 = 1,
}
`ot` now has `ht` as its metatable.
If one now accesses `ot.field1`, Lua checks that there is no `field1` in
`ot` and loads the metatable `ht`. It checks for the `__index` field in
`ht` which points to `ht` again, so it now looks for `field1` in `ht`
and returns its value. We still have the same number of table fields,
but we saved the memory overhead of an empty table.
because when you call Account:new({}) after, the table Account will have a
With `Account:new({})`:
* `ot` is `o`, which is a new table `{}`
* `ht` is `self`, which is the same as `Account`, which is the same as
`ht.__index` or `self.__index`
[...]
I think it should code like this
function Account:new (o)
o = o or {} -- create object if user does not provide one
setmetatable(o, {__index = self})
return o
end
Yes, in that case
* `ot` is `o`
* `mt` is `{__index = self}`
* `it` is `self` (which often will be the same as `Account`)
So this corresponds to the non-hack (three table) version.
HTH,
Philipp