3 Copyright 2007 Antoine Chavasse <a.chavasse@gmail.com>
5 This file is part of Fail.
7 Fail is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 3
9 as published by the Free Software Foundation.
11 Fail is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 module( "fail", package
.seeall
)
21 function class( template
)
23 -- Extract the information we need to setup the class from the
25 superclass
= template
.superclass
28 template
.superclass
= nil
31 -- Instance meta table
32 instancemeta
= { _flNonNative
= true }
34 -- We can't just point the table on itself here,
35 -- because then when we reach the native class up in
36 -- the hierarchy, we no longer have the instance table
37 -- that contains a field pointing to the C++ wrapper, but
38 -- one of the classdef table.
39 -- So we try to rawget up the hierarchy until we hit a native
40 -- table, and then we just get the key from the wrapped C++
41 -- object in _flNativeInstance.
42 function instancemeta
.__index( table, key
)
44 local v
= rawget( table, key
)
45 if v
~= nil then return v
end
47 t
= getmetatable( table )
48 while( rawget( t
, "_flNonNative" ) ) do
49 local v
= rawget( t
, key
)
50 if v
~= nil then return v
end
54 return table._flNativeInstance
[key
]
58 -- set up superclass' (if any) instance meta table to be the meta table
60 -- Also copy the __newindex meta method, so we can write to attributes
61 -- inherited from native classes.
63 instancemeta
.__newindex
= superclass
._flMetatable
.__newindex
64 setmetatable( instancemeta
, superclass
._flMetatable
)
68 -- The class table will be returned and stored globally as
69 -- modulename.classname.
72 -- * a field called _flMetatable, which is the metatable used
73 -- of instances of this class
74 -- * a function called init, that construct this class's part of the
75 -- provided instance table (and call this class' ctor).
76 -- This is called by sub classes' constructors.
77 -- * a metatable that define a __call function that allows the
78 -- creation of a new instance of this class by writing
79 -- instance = someclass( params )
80 -- Its metatable also defines a __newindex function that
81 -- allow to add things to the instance metatable, so member functions
82 -- can then be defined with "function MyClass:func() bla bla end".
84 -- Native classes also define all these things and thus can
85 -- be subclassed (for those that allows it) and instanciated
87 -- This allows to write drop in C++ replacements of existing lua classes
88 -- if it turns out they need to be rewritten for performance reasons,
89 -- provided the lua class(es) to be replaced inherit directly from a native
90 -- class, as a lua class can inherit from a C++ class but not the other way around.
91 classtable
= { _flMetatable
= instancemeta
}
93 function classtable
:init( obj
, ... )
94 -- Copy the keys from the template into the instance,
96 for k
,v
in pairs( template
) do
103 -- Metatable for the class table.
106 function classmeta
.__newindex( table, key
, value
)
107 rawset( instancemeta
, key
, value
)
110 -- The wrapper ctor that will be called by the user to instantiate the class.
111 -- It is not returned directly as a function, because we want the global class
112 -- definition to be a table so we can get things like the correpsonding
113 -- instance metatable from it for inheritance purpose, and the init function.
114 -- Note that native classes also expose their instance metatables the same way.
115 function classmeta
.__call( func
, ... )
118 for k
,v
in pairs( template
) do
122 setmetatable( obj
, instancemeta
)
127 setmetatable( classtable
, classmeta
)