Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- function clone(object)
- local dict = {}
- local function clone(object)
- if (type(object) ~= "table") then
- return object
- elseif (dict[object]) then
- return dict[object]
- end
- dict[object] = {}
- for k, v in pairs(object) do
- dict[object][k] = clone(v)
- end
- return setmetatable(dict[object], clone(getmetatable(object)))
- end
- return clone(object)
- end
- local meta_methods = {
- __add = true, __sub = true, __mul = true, __div = true, __mod = true, __pow = true, __unm = true,
- __concat = true, __len = true,
- __eq = true, __lt = true, __le = true,
- __index = false, __newindex = false, __call = false, __gc = false
- }
- function class(parent)
- local class = {__meta__ = {}}
- if (type(parent) == 'table') then
- -- clone parent class
- class = clone(parent)
- else
- parent = nil
- -- initialize base class
- function class:__construct(...)
- end
- function class:__destruct(...)
- end
- function class:__clone(...)
- end
- end
- class.__meta__.__index = class
- class.__meta__.__gc = function(...)
- self:__destruct(...)
- end
- setmetatable(class, {
- __call = function(self, ...)
- local instance = {}
- setmetatable(instance, class.__meta__)
- instance:__construct(...)
- return instance
- end,
- __newindex = function(t, k, v)
- if (meta_methods[k] == nil or type(v) ~= 'function') then
- rawset(class, k, v)
- elseif (meta_methods[k]) then
- class.__meta__[k] = v
- else
- error("unable to set property")
- end
- end
- })
- -- add additional methods, that should be available for each class
- -- clone instance
- function class:clone(...)
- local class = clone(self)
- class:__clone(...)
- return class
- end
- -- check instance of some other class
- function class:instanceof(class2)
- if (class == class2) then
- return true
- elseif (type(parent) == 'table') then
- return parent:instanceof(class2)
- else
- return false
- end
- end
- -- layer for accessing parent methods in local scope
- function class:parent()
- return setmetatable({}, {
- __newindex = function(...)
- error('unable to modify parent')
- end,
- __index = function(_, k)
- local v = rawget(parent, k)
- if (type(v) == 'function') then
- -- make sure, that parent class is called in child's scope
- return function(_, ...)
- v(self, ...)
- end
- elseif (v) then
- -- return parent property value
- return parent[k]
- else
- -- unable to resolve parent
- return nil
- end
- end
- });
- end
- return class
- end
- -- a
- a = class()
- a.value = 'a'
- function a:print()
- print('class a : ', self.value)
- end
- function a:setWorld()
- self.value = self.value .. " world!"
- end
- -- b
- b = class(a)
- b.value = 'b'
- function b:print()
- print('class b : ', self.value)
- end
- function b:setHallo()
- self.value = 'hallo!'
- self:setWorld()
- end
- -- c
- c = class(b)
- c.value = 'c'
- function c:print()
- print('class c : ', self.value)
- self:parent():print()
- self:setHallo()
- print('class c : ', self.value)
- print(self:parent().value)
- end
- -- test
- test_a = a()
- test_a:print()
- test_b = b()
- test_b:print()
- test_c = c()
- test_c:print()
- -- instanceof
- print(a:instanceof(a), a:instanceof(b), a:instanceof(c))
- print(b:instanceof(a), b:instanceof(b), b:instanceof(c))
- print(c:instanceof(a), c:instanceof(b), c:instanceof(c))
- -- number
- number = class()
- number.value = 0
- function number:__construct(value)
- self.value = value
- end
- function number:__clone(value)
- self.value = value
- end
- -- cast object of instance 'number' to a lua type number
- function number:cast(v)
- if (type(v) == 'table' and v:instanceof(number)) then
- v = v.value
- elseif (type(op1) ~= 'number') then
- v = 0
- end
- return v
- end
- function number:__add(op)
- op = self:cast(op)
- return self:clone(self.value + op)
- end
- ----
- n1 = number(10)
- n2 = number(20)
- print(n1.value, ' + ', n2.value, ' = ', (n1 + n2).value)
- -- money
- money = class(number)
- money.currency = 'EUR'
- function money:__construct(value, currency)
- self:parent():__construct(value)
- self.currency = currency or self.currency
- end
- function money:cast(v)
- if (type(v) == 'table' and v:instanceof(money)) then
- if (self.currency ~= v.currency) then
- error('unable to calculate with operands of different currency!\n')
- end
- v = v.value
- else
- v = self:parent():cast(v)
- end
- return v
- end
- ----
- m1 = money(10)
- m2 = money(20)
- m3 = money(30, 'USD')
- sum = m1 + m2
- print(m1.value, ' + ', m2.value, ' = ', sum.value)
- print(sum.value, ' + ', m3.value, ' = ', (sum + m3).value)
Add Comment
Please, Sign In to add comment