Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Class={}
- Class.__index=Class
- local classes={}
- local current
- local imported={}
- function import(sClasspath)
- assert(type(sClasspath)=="string","Classpath expected to be a string, got "..type(sClasspath))
- local g=setfenv(function() local c=loadfile(sClasspath) c() end,getfenv(1) )
- local okay,error=pcall(g)
- if not okay then
- return false,error
- end
- imported[sClasspath]=true
- return true
- end
- local function getLength(tbl)
- local i=0
- for k,v in pairs(tbl) do
- i=i+1
- end
- return i
- end
- local function uniqueClone(object)
- local t={}
- for k,v in pairs(object) do
- if k~="__index" then
- if type(rawget(object,k))=="table" then
- if getLength(v)==0 then
- t[k]={}
- else
- t[k]=uniqueClone(rawget(object,k))
- end
- else
- t[k]=rawget(object,k)
- end
- end
- end
- return t
- end
- function getImportedClasspaths()
- return imported
- end
- function Class:isDirectSubclassOf(class)
- assert(type(class)=="string" or type(class)=="table","Class expected to be table or string, got "..type(class))
- local tClass=type(class)=="table" and class or classes[class]
- return self.super:getName()==tClass:getName()
- end
- function Class:getSuperclass()
- return self.super
- end
- function Class:getMethods()
- local methods={}
- for k,v in pairs(self) do
- if type(v)=="function" and k~="getClass" and k~="isInstanceOf" then
- methods[k]=v
- end
- end
- return methods
- end
- function Class:getFields()
- local fields={}
- for k,v in pairs(self) do
- if type(v)~="function" then
- fields[k]=v
- end
- end
- return fields
- end
- function Class:getConstructor()
- return self[self:getName()]
- end
- function Class:isSubclassOf(super)
- assert(type(super)=="table" or type(super)=="string","Superclass parameter expected to be string or table, got "..type(super))
- assert(type(self.super)~="nil","Class "..self:getName().." does not extend any classes")
- local status=false
- local tSuper=type(super)=="table" and super or classes[super]
- local curr=self.super
- while status==false do
- if curr:getName()~=tSuper:getName() then
- if curr.super then
- curr=curr.super
- else
- return false
- end
- else
- status=true
- end
- end
- return status
- end
- function Class:isSuperclassOf(subclass)
- assert(type(subclass)=="string" or type(subclass)=="table","Subclass parameter expected to be string or table, got "..type(subclass))
- local status=false
- local tSub=type(subclass)=="table" and subclass or classes[subclass]
- while status==false do
- if self:getName()~=tSub:getName() then
- if tSub.super then
- tSub=tSub.super
- end
- else
- status=true
- end
- end
- return status
- end
- function Class:getSubclasses()
- local sub={}
- for k,v in pairs(classes) do
- if k~=self:getName() then
- if v:isSubclassOf(self) then
- sub[k]=v
- end
- end
- end
- return sub
- end
- function Class:toString()
- return self:getName()..":["..tostring(self):sub(8).."]"
- end
- function Class:getName()
- return self.classname
- end
- function Class:getField(field)
- assert(type(field)=="string","Field name parameter expected to be a string, got "..type(field))
- return type(self[field])~="function" and self[field] or nil
- end
- function Class:getMethod(method)
- assert(type(method)=="string","Method name parameter expected to be a string, got "..type(method))
- return type(self[method])=="function" and self[method] or nil
- end
- function Class:instance()
- local c=self
- local instance=uniqueClone(self)
- instance["classname"]=nil
- instance["getClass"]=function()
- return setmetatable({},{__index=self,__newindex=function(t,k,v) error("Attempt to modify class [ "..self:getName().." ] at field [ "..k.." ]") end} )
- end
- instance["isInstanceOf"]=function(obj,class)
- if type(class)=="string" then
- return c:getName()==class
- elseif type(class)=="table" then
- return class:getName()==c:getName()
- end
- end
- instance["clone"]=function(self)
- return setmetatable(uniqueClone(self),getmetatable(self))
- end
- if type(self.super)=="table" then
- instance.super=self.super:create()
- instance.super.__index=instance.super
- local MT={}
- if type(getmetatable(instance.super))=="table" then
- MT=getmetatable(instance.super)
- MT["__call"]=function(t,...) return self.super:create(...) end
- elseif type(getmetatable(instance.super))=="nil" then
- MT={__call=function(t,...) return self.super:create(...) end}
- end
- setmetatable(instance.super,MT)
- setmetatable(instance,instance.super)
- end
- return instance
- end
- function Class:create(...)
- local instance=self:instance()
- instance[self:getName()](instance,...)
- return instance
- end
- function class(sName)
- classes[sName]=setmetatable({},{__className=sName,__index=Class})--,__propertyMap={},__setters={},__getters={}})
- getmetatable(classes[sName]).__call=function(t,...) return classes[sName]:create(...) end
- current=classes[sName]
- return function(tBody)
- if not tBody[sName] or type(tBody[sName])~="function" then
- error("Class needs a constructor",2)
- end
- tBody["classname"]=sName
- tBody["super"]=nil
- classes[sName]=setmetatable(tBody,getmetatable(classes[sName]))
- _G[classes[sName]:getName()]=classes[sName]
- return classes[sName]
- end
- end
- function extends(sName)
- local curClass=getmetatable(current).__className
- assert(classes[sName],"Class "..sName.." does not exist")
- classes[curClass]["classname"]=getmetatable(curClass).__className
- return function(tBody)
- if not tBody[curClass] or type(tBody[curClass])~="function" then
- error("Class ["..curClass.."] needs a constructor",2)
- end
- tBody["classname"]=curClass
- tBody["super"]=classes[sName]
- classes[curClass]=setmetatable(tBody,getmetatable(classes[curClass]))
- _G[curClass]=classes[curClass]
- return classes[curClass]
- end
- end
- _G.class=class
- _G.extends=extends
Advertisement
Add Comment
Please, Sign In to add comment