Guest User

Untitled

a guest
Jun 21st, 2018
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.21 KB | None | 0 0
  1.  
  2. function clone(object)
  3. local dict = {}
  4.  
  5. local function clone(object)
  6. if (type(object) ~= "table") then
  7. return object
  8. elseif (dict[object]) then
  9. return dict[object]
  10. end
  11.  
  12. dict[object] = {}
  13.  
  14. for k, v in pairs(object) do
  15. dict[object][k] = clone(v)
  16. end
  17.  
  18. return setmetatable(dict[object], clone(getmetatable(object)))
  19. end
  20.  
  21. return clone(object)
  22. end
  23.  
  24. local meta_methods = {
  25. __add = true, __sub = true, __mul = true, __div = true, __mod = true, __pow = true, __unm = true,
  26. __concat = true, __len = true,
  27. __eq = true, __lt = true, __le = true,
  28. __index = false, __newindex = false, __call = false, __gc = false
  29. }
  30.  
  31. function class(parent)
  32. local class = {__meta__ = {}}
  33.  
  34. if (type(parent) == 'table') then
  35. -- clone parent class
  36. class = clone(parent)
  37. else
  38. parent = nil
  39.  
  40. -- initialize base class
  41. function class:__construct(...)
  42. end
  43.  
  44. function class:__destruct(...)
  45. end
  46.  
  47. function class:__clone(...)
  48. end
  49. end
  50.  
  51. class.__meta__.__index = class
  52. class.__meta__.__gc = function(...)
  53. self:__destruct(...)
  54. end
  55.  
  56. setmetatable(class, {
  57. __call = function(self, ...)
  58. local instance = {}
  59.  
  60. setmetatable(instance, class.__meta__)
  61. instance:__construct(...)
  62.  
  63. return instance
  64. end,
  65. __newindex = function(t, k, v)
  66. if (meta_methods[k] == nil or type(v) ~= 'function') then
  67. rawset(class, k, v)
  68. elseif (meta_methods[k]) then
  69. class.__meta__[k] = v
  70. else
  71. error("unable to set property")
  72. end
  73. end
  74. })
  75.  
  76. -- add additional methods, that should be available for each class
  77. -- clone instance
  78. function class:clone(...)
  79. local class = clone(self)
  80.  
  81. class:__clone(...)
  82.  
  83. return class
  84. end
  85.  
  86. -- check instance of some other class
  87. function class:instanceof(class2)
  88. if (class == class2) then
  89. return true
  90. elseif (type(parent) == 'table') then
  91. return parent:instanceof(class2)
  92. else
  93. return false
  94. end
  95. end
  96.  
  97. -- layer for accessing parent methods in local scope
  98. function class:parent()
  99. return setmetatable({}, {
  100. __newindex = function(...)
  101. error('unable to modify parent')
  102. end,
  103. __index = function(_, k)
  104. local v = rawget(parent, k)
  105.  
  106. if (type(v) == 'function') then
  107. -- make sure, that parent class is called in child's scope
  108. return function(_, ...)
  109. v(self, ...)
  110. end
  111. elseif (v) then
  112. -- return parent property value
  113. return parent[k]
  114. else
  115. -- unable to resolve parent
  116. return nil
  117. end
  118. end
  119. });
  120. end
  121.  
  122. return class
  123. end
  124.  
  125. -- a
  126. a = class()
  127. a.value = 'a'
  128.  
  129. function a:print()
  130. print('class a : ', self.value)
  131. end
  132.  
  133. function a:setWorld()
  134. self.value = self.value .. " world!"
  135. end
  136.  
  137. -- b
  138. b = class(a)
  139. b.value = 'b'
  140.  
  141. function b:print()
  142. print('class b : ', self.value)
  143. end
  144.  
  145. function b:setHallo()
  146. self.value = 'hallo!'
  147.  
  148. self:setWorld()
  149. end
  150.  
  151. -- c
  152. c = class(b)
  153. c.value = 'c'
  154.  
  155. function c:print()
  156. print('class c : ', self.value)
  157.  
  158. self:parent():print()
  159. self:setHallo()
  160.  
  161. print('class c : ', self.value)
  162.  
  163. print(self:parent().value)
  164. end
  165.  
  166. -- test
  167. test_a = a()
  168. test_a:print()
  169.  
  170. test_b = b()
  171. test_b:print()
  172.  
  173. test_c = c()
  174. test_c:print()
  175.  
  176. -- instanceof
  177. print(a:instanceof(a), a:instanceof(b), a:instanceof(c))
  178. print(b:instanceof(a), b:instanceof(b), b:instanceof(c))
  179. print(c:instanceof(a), c:instanceof(b), c:instanceof(c))
  180.  
  181. -- number
  182. number = class()
  183. number.value = 0
  184.  
  185. function number:__construct(value)
  186. self.value = value
  187. end
  188. function number:__clone(value)
  189. self.value = value
  190. end
  191.  
  192. -- cast object of instance 'number' to a lua type number
  193. function number:cast(v)
  194. if (type(v) == 'table' and v:instanceof(number)) then
  195. v = v.value
  196. elseif (type(op1) ~= 'number') then
  197. v = 0
  198. end
  199.  
  200. return v
  201. end
  202.  
  203. function number:__add(op)
  204. op = self:cast(op)
  205.  
  206. return self:clone(self.value + op)
  207. end
  208.  
  209. ----
  210. n1 = number(10)
  211. n2 = number(20)
  212.  
  213. print(n1.value, ' + ', n2.value, ' = ', (n1 + n2).value)
  214.  
  215. -- money
  216. money = class(number)
  217. money.currency = 'EUR'
  218.  
  219. function money:__construct(value, currency)
  220. self:parent():__construct(value)
  221.  
  222. self.currency = currency or self.currency
  223. end
  224.  
  225. function money:cast(v)
  226. if (type(v) == 'table' and v:instanceof(money)) then
  227. if (self.currency ~= v.currency) then
  228. error('unable to calculate with operands of different currency!\n')
  229. end
  230.  
  231. v = v.value
  232. else
  233. v = self:parent():cast(v)
  234. end
  235.  
  236. return v
  237. end
  238.  
  239. ----
  240. m1 = money(10)
  241. m2 = money(20)
  242. m3 = money(30, 'USD')
  243.  
  244. sum = m1 + m2
  245.  
  246. print(m1.value, ' + ', m2.value, ' = ', sum.value)
  247. print(sum.value, ' + ', m3.value, ' = ', (sum + m3).value)
Add Comment
Please, Sign In to add comment