Guest User

Untitled

a guest
Jul 16th, 2018
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 3.15 KB | None | 0 0
  1. --------------------------------------------------------------------------
  2. -- minimal class system for lua
  3. -- features:
  4. -- * single/pseudo-multiple inheritance
  5. -- * fast, no functions involved in field/method dispatch
  6. -- * absolutely zero hand-holding :)
  7. -- * python-ish syntax:
  8. --
  9. -- local YourClass = class.YourClassName(superclass1,superclass2...)
  10. --
  11. -- class names are intentionally polluting global namespace
  12. -- to prevent name conflicts, cache into local if you're creating
  13. -- lots of instances.
  14. --
  15. -- superclasses can be just tables with fields you wish to have included
  16. -- in your class (ie mixins, unless you call super constructor)
  17. --
  18. -- examples:
  19. --
  20. -- class.ClassA {
  21. --    staticfield1=1,
  22. --    staticfield2=2,
  23. --    method=function(self,blah)
  24. --        -- methods can be defined like this, too
  25. --    end
  26. -- }
  27. -- function ClassA:new(arg,arg2)
  28. --    self.arg = arg
  29. --    self.arg2 = arg2
  30. --    -- self is prepared instance with static fields from superclasses
  31. -- end
  32. --
  33. -- instance = ClassA(arg,arg2) -- invoke class to get instance (calls :new)
  34. --
  35. -- inheritance:
  36. -- class.ClassB(ClassA, {
  37. --     staticfield1=3 -- this field will be overshadowed by ClassA!
  38. -- })
  39. -- function ClassB:new(arg,arg2)
  40. --     ClassA.new(self,arg,arg2) -- optionally call superclass
  41. -- end
  42. -- ClassB.staticfield2=3 -- this field will override superclasses
  43. --
  44. -- "multiple" inheritance:
  45. --
  46. -- class.ClassC()
  47. -- class.ClassD(ClassB,ClassC)
  48. -- function ClassD:new(arg1,arg2)
  49. --   ClassB.new(self,arg1,arg2) -- which super calls to include is up to you of course :)
  50. --   ClassC.new(self,arg1,arg2)
  51. -- end
  52. --
  53. -- --sd
  54.  
  55.  
  56. -- recursively walk list of mixin classes and patch em into the target class
  57. local function addsupers(target,supers)
  58.     for i=1,#supers do -- faster than ipairs
  59.         local super = supers[i]
  60.         for k,v in pairs(super) do
  61.             if not target[k] then
  62.                 target[k] = v
  63.             end
  64.         end
  65.         addsupers(target, super.supers or {})
  66.     end
  67. end
  68.  
  69. -- create new instance
  70. local function instantiate(tk,...)
  71.     local instance={}
  72.     setmetatable(instance,tk.classmeta)
  73.     return instance:new(...) or instance
  74. end
  75.  
  76. -- superclasses are patched into our class metatable. we're trading speed for correctness,
  77. -- but it's usually safe to assume superclasses are final just before first object instance
  78. local function fix_supers(tk,...)
  79.     tk.__call = instantiate
  80.     addsupers(tk,tk.supers)
  81.     return instantiate(tk,...)
  82. end
  83.  
  84. class = setmetatable({}, {
  85.     __index = function(klstab,kls)
  86.         if rawget(_G, kls) then
  87.             error("There is already '"..kls.."' in the global namespace!")
  88.         end
  89.         return function(...)
  90.             local meta = {}
  91.             local supers = {...}
  92.             meta.classmeta = {__index=meta} -- this is the actual metatable for instances
  93.             meta.class = kls -- class name, just for reference
  94.             meta.supers = supers -- list of superclasses
  95.             meta.__index = supers[1]
  96.             meta.__call = fix_supers
  97.             rawset(_G, kls, setmetatable(meta, meta))
  98.             return meta
  99.         end
  100.     end
  101. })
  102.  
  103. return class
Add Comment
Please, Sign In to add comment