Spoiler
local function new( object )
local mt = {}
for k, v in pairs( getmetatable( object ) ) do
mt[ k ] = v
end
mt.inherits[ #mt.inherits + 1 ] = object.class()
mt.super = object
return setmetatable( {}, mt )
end
local Object = setmetatable( {}, {
__call = function( t, ... )
local tArgs = { ... }
if type( tArgs[ 1 ] ) == "table" and tArgs[ 1 ].name then
local n = new( t )
local mt = getmetatable( n )
mt.inherits[ #mt.inherits + 1 ] = tArgs[ 1 ].name
for k, v in pairs( tArgs[ 1 ] ) do
n[ k ] = v
end
return n
end
return new( t )
end,
inherits = {"Object"},
__super = {},
__index = function( t, k )
return t[ k ] or getmetatable( t ).__super[ k ]
end,
__newindex = function( t, k, v )
if type( v ) == "function" then
local env = getfenv( v )
env.this, env.super = t, getmetatable( t ).__super
end
rawset( t, k, v )
end,
})
Object.class = function()
local inherits = getmetatable( this ).inherits
return inherits[ #inherits ]
end
Object.extends = function( s )
local inherits = getmetatable( this ).inherits
for k, v in pairs( inherits ) do
if v == s then
return true
end
end
return false
end
Window = Object{
name = "Window",
}
For some reason, calling Object.class() after declaring Window returns "Window" - obviously I don't want that to happen. In addition, calling Window.class() is doing something weird, I get java.lang.arrayIndexOutofBoundsException - it's got to be going in circles somehow.