Kouksi44

Lua Class API

Aug 1st, 2015
360
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.22 KB | None | 0 0
  1.  
  2.  
  3.         Class={}
  4.         Class.__index=Class
  5.  
  6.         local classes={}
  7.         local current
  8.         local imported={}
  9.  
  10. function import(sClasspath)
  11.     assert(type(sClasspath)=="string","Classpath expected to be a string, got "..type(sClasspath))
  12.         local g=setfenv(function() local c=loadfile(sClasspath) c() end,getfenv(1) )
  13.         local okay,error=pcall(g)
  14.         if not okay then
  15.             return false,error
  16.         end
  17.         imported[sClasspath]=true
  18.         return true
  19. end
  20.    
  21.     local function getLength(tbl)
  22.         local i=0
  23.         for k,v in pairs(tbl) do
  24.             i=i+1
  25.         end
  26.        
  27.         return i
  28.     end
  29.    
  30.     local function uniqueClone(object)
  31.         local t={}
  32.         for k,v in pairs(object) do
  33.             if k~="__index" then
  34.                 if type(rawget(object,k))=="table" then
  35.                     if getLength(v)==0 then
  36.                         t[k]={}
  37.                     else
  38.                         t[k]=uniqueClone(rawget(object,k))
  39.                     end
  40.                 else
  41.                     t[k]=rawget(object,k)
  42.                 end
  43.             end
  44.         end
  45.             return t
  46.         end
  47.        
  48.         function getImportedClasspaths()
  49.             return imported
  50.         end
  51.                    
  52.         function Class:isDirectSubclassOf(class)
  53.             assert(type(class)=="string" or type(class)=="table","Class expected to be table or string, got "..type(class))
  54.             local tClass=type(class)=="table" and class or classes[class]
  55.             return self.super:getName()==tClass:getName()
  56.         end
  57.  
  58.         function Class:getSuperclass()
  59.             return self.super
  60.         end
  61.  
  62.         function Class:getMethods()
  63.             local methods={}
  64.             for k,v in pairs(self) do
  65.                 if type(v)=="function" and k~="getClass" and k~="isInstanceOf" then
  66.                     methods[k]=v
  67.                 end
  68.             end
  69.             return methods
  70.         end
  71.  
  72.         function Class:getFields()
  73.             local fields={}
  74.             for k,v in pairs(self) do
  75.                 if type(v)~="function" then
  76.                     fields[k]=v
  77.                 end
  78.             end
  79.             return fields
  80.         end
  81.        
  82.         function Class:getConstructor()
  83.             return self[self:getName()]
  84.         end
  85.        
  86.         function Class:isSubclassOf(super)
  87.            
  88.             assert(type(super)=="table" or type(super)=="string","Superclass parameter expected to be string or table, got "..type(super))
  89.             assert(type(self.super)~="nil","Class "..self:getName().." does not extend any classes")
  90.             local status=false
  91.             local tSuper=type(super)=="table" and super or classes[super]
  92.             local curr=self.super
  93.            
  94.                 while status==false do
  95.                     if curr:getName()~=tSuper:getName() then
  96.                         if curr.super then
  97.                             curr=curr.super
  98.                         else
  99.                             return false
  100.                         end
  101.                     else
  102.                         status=true
  103.                     end
  104.                 end
  105.            
  106.             return status
  107.         end
  108.                
  109.         function Class:isSuperclassOf(subclass)
  110.             assert(type(subclass)=="string" or type(subclass)=="table","Subclass parameter expected to be string or table, got "..type(subclass))
  111.             local status=false
  112.             local tSub=type(subclass)=="table" and subclass or classes[subclass]
  113.            
  114.            
  115.             while status==false do
  116.                 if self:getName()~=tSub:getName() then
  117.                     if tSub.super then
  118.                         tSub=tSub.super
  119.                     end
  120.                 else
  121.                     status=true
  122.                 end
  123.             end
  124.             return status
  125.         end
  126.        
  127.         function Class:getSubclasses()
  128.            
  129.             local sub={}
  130.             for k,v in pairs(classes) do
  131.                 if k~=self:getName() then
  132.                     if v:isSubclassOf(self) then
  133.                         sub[k]=v
  134.                     end
  135.                 end
  136.             end
  137.             return sub
  138.         end
  139.  
  140.         function Class:toString()
  141.             return self:getName()..":["..tostring(self):sub(8).."]"
  142.         end
  143.  
  144.         function Class:getName()
  145.             return self.classname
  146.         end
  147.        
  148.         function Class:getField(field)
  149.             assert(type(field)=="string","Field name parameter expected to be a string, got "..type(field))
  150.             return type(self[field])~="function" and self[field] or nil
  151.         end
  152.        
  153.         function Class:getMethod(method)
  154.             assert(type(method)=="string","Method name parameter expected to be a string, got "..type(method))
  155.            
  156.             return type(self[method])=="function" and self[method] or nil
  157.         end
  158.        
  159.         function Class:instance()
  160.  
  161.             local c=self
  162.             local instance=uniqueClone(self)
  163.             instance["classname"]=nil
  164.            
  165.             instance["getClass"]=function()
  166.                 return setmetatable({},{__index=self,__newindex=function(t,k,v) error("Attempt to modify class [ "..self:getName().." ] at field [ "..k.." ]") end} )
  167.             end
  168.             instance["isInstanceOf"]=function(obj,class)
  169.                 if type(class)=="string" then
  170.                     return c:getName()==class
  171.                 elseif type(class)=="table" then
  172.                     return class:getName()==c:getName()
  173.                 end
  174.             end
  175.            
  176.             instance["clone"]=function(self)
  177.                  return setmetatable(uniqueClone(self),getmetatable(self))
  178.              end
  179.        
  180.              
  181.             if type(self.super)=="table" then
  182.                 instance.super=self.super:create()
  183.                 instance.super.__index=instance.super
  184.                
  185.                 local MT={}
  186.                 if type(getmetatable(instance.super))=="table" then
  187.                      MT=getmetatable(instance.super)
  188.                     MT["__call"]=function(t,...)  return self.super:create(...) end
  189.                 elseif type(getmetatable(instance.super))=="nil" then
  190.                      MT={__call=function(t,...)  return self.super:create(...) end}
  191.                  end
  192.                 setmetatable(instance.super,MT)
  193.                 setmetatable(instance,instance.super)
  194.             end
  195.             return instance
  196.         end
  197.  
  198.         function Class:create(...)
  199.             local instance=self:instance()
  200.             instance[self:getName()](instance,...)
  201.             return instance
  202.         end
  203.  
  204.  
  205.         function class(sName)
  206.             classes[sName]=setmetatable({},{__className=sName,__index=Class})--,__propertyMap={},__setters={},__getters={}})
  207.             getmetatable(classes[sName]).__call=function(t,...)  return classes[sName]:create(...) end
  208.             current=classes[sName]
  209.             return function(tBody)
  210.                 if not tBody[sName] or type(tBody[sName])~="function" then
  211.                     error("Class needs a constructor",2)
  212.                 end
  213.                 tBody["classname"]=sName
  214.                 tBody["super"]=nil
  215.                 classes[sName]=setmetatable(tBody,getmetatable(classes[sName]))
  216.                 _G[classes[sName]:getName()]=classes[sName]
  217.                 return classes[sName]
  218.             end
  219.         end
  220.  
  221.         function extends(sName)
  222.             local curClass=getmetatable(current).__className
  223.             assert(classes[sName],"Class "..sName.." does not exist")
  224.             classes[curClass]["classname"]=getmetatable(curClass).__className
  225.             return function(tBody)
  226.                 if not tBody[curClass] or type(tBody[curClass])~="function" then
  227.                     error("Class ["..curClass.."] needs a constructor",2)
  228.                 end
  229.                 tBody["classname"]=curClass
  230.                 tBody["super"]=classes[sName]
  231.                 classes[curClass]=setmetatable(tBody,getmetatable(classes[curClass]))
  232.                 _G[curClass]=classes[curClass]
  233.                 return classes[curClass]
  234.             end
  235.         end
  236.        
  237.         _G.class=class
  238.         _G.extends=extends
Advertisement
Add Comment
Please, Sign In to add comment