├── README.md ├── init.lua └── rocks ├── class-0.5.0-0.rockspec └── class-scm-1.rockspec /README.md: -------------------------------------------------------------------------------- 1 | Object Classes for Lua 2 | ---------------------- 3 | 4 | This package provide simple object-oriented capabilities to Lua. 5 | Each class is defined with a metatable, which contains methods. 6 | Inheritance is achieved by setting metatables over metatables. 7 | An efficient type checking is provided. 8 | 9 | ## Typical Example 10 | 11 | ```lua 12 | local class = require 'class' 13 | 14 | -- define some dummy A class 15 | local A = class('A') 16 | 17 | function A:__init(stuff) 18 | self.stuff = stuff 19 | end 20 | 21 | function A:run() 22 | print(self.stuff) 23 | end 24 | 25 | -- define some dummy B class, inheriting from A 26 | local B = class('B', 'A') 27 | 28 | function B:run5() 29 | for i=1,5 do 30 | print(self.stuff) 31 | end 32 | end 33 | 34 | -- create some instances of both classes 35 | local a = A('hello world from A') 36 | local b = B('hello world from B') 37 | 38 | -- run stuff 39 | a:run() 40 | b:run() 41 | b:run5() 42 | ``` 43 | 44 | ## Documentation 45 | 46 | First, require the package 47 | ```lua 48 | local class = require 'class' 49 | ``` 50 | Note that `class` does not clutter the global namespace. 51 | 52 | Class metatables are then created with `class(name)` or equivalently `class.new(name)`. 53 | ```lua 54 | local A = class('A') 55 | local B = class('B', 'A') -- B inherit from A 56 | ``` 57 | 58 | You then have to fill-up the returned metatable with methods. 59 | ```lua 60 | function A:myMethod() 61 | -- do something 62 | end 63 | ``` 64 | 65 | There are two special methods: `new()`, which already exists when the class is created and _should not be overrided_ 66 | and `__init()` which is called by `new()` at the creation of the class. 67 | ```lua 68 | function A:__init(args) 69 | -- do something with args 70 | -- note that self exists 71 | end 72 | ``` 73 | 74 | Creation of an instance is then achieved with the `new()` function or (equivalently) using the Lua `__call` metamethod: 75 | ```lua 76 | local a = A('blah blah') -- an instance of A 77 | local aa = A.new('blah blah') -- equivalent of the above 78 | ``` 79 | 80 | ### `class.new(name[, parentname])` 81 | 82 | Creates a new class called `name`, which might optionally inherit from `parentname`. 83 | Returns a table, in which methods should be defined. 84 | 85 | Note that the returned table is not the metatable, but a _constructor_ table (with a `__call` 86 | function defined). In that respect, one can use the following shorthand: 87 | ```lua 88 | local A = class.new('A') 89 | local a = A.new() -- instance. 90 | local aa = A() -- another instance (shorthand). 91 | ``` 92 | 93 | There is also a shorthand`class.new()`, which is `class()`. 94 | 95 | ### `class.factory(name)` 96 | 97 | Return a new (empty) instance of the class `name`. No `__init` method will be called. 98 | 99 | ### `class.metatable(name)` 100 | 101 | Return the metatable (i.e. the table containing all methods) related to class `name`. 102 | 103 | ### `class.type(obj)` 104 | 105 | Return the type of the object `obj` (if this is a known class), or the type 106 | returned by the standard lua `type()` function (if it is not known). 107 | 108 | ### `class.istype(obj, name)` 109 | 110 | Check is `obj` is an instance (or a child) of class `name`. Returns a boolean. 111 | 112 | 113 | -------------------------------------------------------------------------------- /init.lua: -------------------------------------------------------------------------------- 1 | local argcheck = require 'argcheck' 2 | local argcheckenv = require 'argcheck.env' 3 | local doc = require 'argcheck.doc' 4 | local ffi 5 | 6 | pcall(function() 7 | ffi = require 'ffi' 8 | end) 9 | 10 | doc[[ 11 | Object Classes for Lua 12 | ---------------------- 13 | 14 | This package provide simple object-oriented capabilities to Lua. 15 | Each class is defined with a metatable, which contains methods. 16 | Inheritance is achieved by setting metatables over metatables. 17 | An efficient type checking is provided. 18 | 19 | ## Typical Example 20 | 21 | ```lua 22 | local class = require 'class' 23 | 24 | -- define some dummy A class 25 | local A = class('A') 26 | 27 | function A:__init(stuff) 28 | self.stuff = stuff 29 | end 30 | 31 | function A:run() 32 | print(self.stuff) 33 | end 34 | 35 | -- define some dummy B class, inheriting from A 36 | local B = class('B', 'A') 37 | 38 | function B:__init(stuff) 39 | A.__init(self, stuff) -- call the parent init 40 | end 41 | 42 | function B:run5() 43 | for i=1,5 do 44 | print(self.stuff) 45 | end 46 | end 47 | 48 | -- create some instances of both classes 49 | local a = A('hello world from A') 50 | local b = B('hello world from B') 51 | 52 | -- run stuff 53 | a:run() 54 | b:run() 55 | b:run5() 56 | ``` 57 | 58 | ## Documentation 59 | 60 | First, require the package 61 | ```lua 62 | local class = require 'class' 63 | ``` 64 | Note that `class` does not clutter the global namespace. 65 | 66 | Class metatables are then created with `class(name)` or equivalently `class.new(name)`. 67 | ```lua 68 | local A = class('A') 69 | local B = class('B', 'A') -- B inherit from A 70 | ``` 71 | 72 | You then have to fill-up the returned metatable with methods. 73 | ```lua 74 | function A:myMethod() 75 | -- do something 76 | end 77 | ``` 78 | 79 | There are two special methods: `new()`, which already exists when the class is created and _should not be overrided_ 80 | and `__init()` which is called by `new()` at the creation of the class. 81 | ```lua 82 | function A:__init(args) 83 | -- do something with args 84 | -- note that self exists 85 | end 86 | ``` 87 | 88 | Creation of an instance is then achieved with the `new()` function or (equivalently) using the Lua `__call` metamethod: 89 | ```lua 90 | local a = A('blah blah') -- an instance of A 91 | local aa = A.new('blah blah') -- equivalent of the above 92 | ``` 93 | 94 | ]] 95 | 96 | local class = {} 97 | local classes = {} 98 | local isofclass = {} 99 | local ctypes = {} 100 | 101 | -- create a constructor table 102 | local function constructortbl(metatable) 103 | local ct = {} 104 | setmetatable(ct, { 105 | __index=metatable, 106 | __newindex=metatable, 107 | __metatable=metatable, 108 | __call=function(self, ...) 109 | return self.new(...) 110 | end 111 | }) 112 | return ct 113 | end 114 | 115 | class.new = argcheck{ 116 | doc = [[ 117 | ### `class.new(@ARGP)` 118 | 119 | Creates a new class called `name`, which might optionally inherit from `parentname`. 120 | Returns a table, in which methods should be defined. 121 | 122 | Note that the returned table is not the metatable, but a _constructor_ table (with a `__call` 123 | function defined). In that respect, one can use the following shorthand: 124 | ```lua 125 | local A = class.new('A') 126 | local a = A.new() -- instance. 127 | local aa = A() -- another instance (shorthand). 128 | ``` 129 | 130 | There is also a shorthand `class.new()`, which is `class()`. 131 | 132 | ]], 133 | {name="name", type="string", doc="class name"}, 134 | {name="parentname", type="string", opt=true, doc="parent class name"}, 135 | {name="ctype", type="cdata", opt=true, doc="ctype which should be considered as of class name"}, 136 | call = 137 | function(name, parentname, ctype) 138 | local class = {__typename = name} 139 | 140 | assert(not classes[name], string.format('class <%s> already exists', name)) 141 | if ctype then 142 | local ctype_id = tonumber(ctype) 143 | assert(ctype_id, 'invalid ffi ctype') 144 | assert(not ctypes[ctype_id], string.format('ctype <%s> already considered as <%s>', tostring(ctype), ctypes[ctype_id])) 145 | ctypes[ctype_id] = name 146 | end 147 | 148 | class.__index = class 149 | 150 | class.__factory = 151 | function() 152 | local self = {} 153 | setmetatable(self, class) 154 | return self 155 | end 156 | 157 | class.__init = 158 | function() 159 | end 160 | 161 | class.new = 162 | function(...) 163 | local self = class.__factory() 164 | self:__init(...) 165 | return self 166 | end 167 | 168 | classes[name] = class 169 | isofclass[name] = {[name]=true} 170 | 171 | if parentname then 172 | local parent = classes[parentname] 173 | assert(parent, string.format('parent class <%s> does not exist', parentname)) 174 | setmetatable(class, parent) 175 | 176 | -- consider as type of parent 177 | while parent do 178 | isofclass[parent.__typename][name] = true 179 | parent = getmetatable(parent) 180 | end 181 | 182 | return constructortbl(class), classes[parentname] 183 | else 184 | return constructortbl(class) 185 | end 186 | end 187 | } 188 | 189 | class.factory = argcheck{ 190 | doc = [[ 191 | ### `class.factory(name)` 192 | 193 | Return a new (empty) instance of the class `name`. No `__init` method will be called. 194 | 195 | ]], 196 | {name="name", type="string"}, 197 | call = 198 | function(name) 199 | assert(classes[name], string.format('unknown class <%s>', name)) 200 | return class[name].__factory() 201 | end 202 | } 203 | 204 | class.metatable = argcheck{ 205 | doc = [[ 206 | ### `class.metatable(name)` 207 | 208 | Return the metatable (i.e. the table containing all methods) related to class `name`. 209 | 210 | ]], 211 | {name="name", type="string"}, 212 | call = 213 | function(name) 214 | return classes[name] 215 | end 216 | } 217 | 218 | doc[[ 219 | ### `class.type(obj)` 220 | 221 | Return the type of the object `obj` (if this is a known class), or the type 222 | returned by the standard lua `type()` function (if it is not known). 223 | 224 | ]] 225 | 226 | function class.type(obj) 227 | local tname = type(obj) 228 | 229 | local objname 230 | if tname == 'cdata' then 231 | objname = ctypes[tonumber(ffi.typeof(obj))] 232 | elseif tname == 'userdata' or tname == 'table' then 233 | local mt = getmetatable(obj) 234 | if mt then 235 | objname = rawget(mt, '__typename') 236 | end 237 | end 238 | 239 | if objname then 240 | return objname 241 | else 242 | return tname 243 | end 244 | end 245 | 246 | doc[[ 247 | ### `class.istype(obj, name)` 248 | 249 | Check is `obj` is an instance (or a child) of class `name`. Returns a boolean. 250 | 251 | ]] 252 | 253 | function class.istype(obj, typename) 254 | local tname = type(obj) 255 | 256 | local objname 257 | if tname == 'cdata' then 258 | objname = ctypes[tonumber(ffi.typeof(obj))] 259 | elseif tname == 'userdata' or tname == 'table' then 260 | local mt = getmetatable(obj) 261 | if mt then 262 | objname = rawget(mt, '__typename') 263 | end 264 | end 265 | 266 | if objname then -- we are now sure it is one of our object 267 | local valid = rawget(isofclass, typename) 268 | if valid then 269 | return rawget(valid, objname) or false 270 | else 271 | return objname == typename -- it might be some other type system 272 | end 273 | else 274 | return tname == typename 275 | end 276 | end 277 | 278 | -- make sure argcheck understands those types 279 | argcheckenv.istype = class.istype 280 | 281 | -- allow class() instead of class.new() 282 | setmetatable(class, {__call= 283 | function(self, ...) 284 | return self.new(...) 285 | end}) 286 | 287 | return class 288 | -------------------------------------------------------------------------------- /rocks/class-0.5.0-0.rockspec: -------------------------------------------------------------------------------- 1 | package = "class" 2 | version = "0.5.0-0" 3 | 4 | source = { 5 | url = "git://github.com/torch/class.git", 6 | tag = "0.5.0-0" 7 | } 8 | 9 | description = { 10 | summary = "Class Objects for Lua", 11 | detailed = [[ 12 | Simple object-oriented system for Lua, with classes supporting 13 | inheritance. 14 | ]], 15 | homepage = "https://github.com/torch/class", 16 | license = "BSD" 17 | } 18 | 19 | dependencies = { 20 | "lua >= 5.1", 21 | "argcheck ~> 0.5" 22 | } 23 | 24 | build = { 25 | type = "builtin", 26 | modules = { 27 | ["class.init"] = "init.lua" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /rocks/class-scm-1.rockspec: -------------------------------------------------------------------------------- 1 | package = "class" 2 | version = "scm-1" 3 | 4 | source = { 5 | url = "git://github.com/torch/class.git" 6 | } 7 | 8 | description = { 9 | summary = "Class Objects for Lua", 10 | detailed = [[ 11 | Simple object-oriented system for Lua, with classes supporting 12 | inheritance. 13 | ]], 14 | homepage = "https://github.com/torch/class", 15 | license = "BSD" 16 | } 17 | 18 | dependencies = { 19 | "lua >= 5.1", 20 | "argcheck >= 1" 21 | } 22 | 23 | build = { 24 | type = "builtin", 25 | modules = { 26 | ["class.init"] = "init.lua" 27 | } 28 | } 29 | --------------------------------------------------------------------------------