Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 75 additions & 0 deletions lua/spec/class_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ describe('class', function()
return 'Animal'
end

function Animal:__tostring()
return self:type()
end

function Animal:size()
error('abstract')
end
Expand All @@ -32,6 +36,12 @@ describe('class', function()
return 4
end

local SpecialCat = Class.new(Cat)

function SpecialCat:makeSound()
return 'Meow'
end

describe('class operations', function()
it('base class', function ()
local a1 = Animal()
Expand All @@ -48,6 +58,56 @@ describe('class', function()
end)
end)

describe('super', function()
it('assert single proxy', function ()
local sc1 = SpecialCat(5)

assert.is_true(sc1:super() == sc1:super())
end)

it('access super methods', function ()
local c1 = Cat(5)

assert.equal('Animal', c1:super():type())
assert.error(function() return c1:super():numLegs() end)

local sc1 = SpecialCat(5)

assert.equal('Cat', sc1:super():type())
assert.equal(4, sc1:super():numLegs())
assert.error(function() return sc1:super():makeSound() end)
end)

it('call super metamethods', function ()
local c1 = Cat(5)

assert.equal('Cat', tostring(c1))
assert.equal('Animal', tostring(c1:super()))
end)

it('access instance variable from super', function ()
local c1 = Cat(5)

assert.equal(5, c1:super()._size)
end)

it('set instance variable from super', function ()
local c1 = Cat(5)

c1:super()._size = 20

assert.are_not_equal(5, c1._size)
assert.equal(20, c1._size)
assert.equal(20, c1:size())
end)

it('error if getting grandparent class', function ()
local sc1 = SpecialCat(5)

assert.error(function() return sc1:super():super() end, 'Cannot create proxy from a super proxy')
end)
end)

describe('instanceOf', function()
it('with same class', function ()
local c1 = Cat(5)
Expand All @@ -62,5 +122,20 @@ describe('class', function()
local a1 = Animal()
assert.is_false(Class.instanceOf(a1, Cat))
end)

it('with super', function ()
local c1 = Cat(5)
assert.is_true(Class.instanceOf(c1:super(), Animal))
assert.is_false(Class.instanceOf(c1:super(), Cat))
end)

it('with super of grandchild', function ()
local sc1 = SpecialCat(5)

local superSc1 = sc1:super()

assert.is_true(Class.instanceOf(superSc1, Cat))
assert.is_true(Class.instanceOf(superSc1, Animal))
end)
end)
end)
40 changes: 40 additions & 0 deletions lua/wikis/commons/Class.lua
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ Class.PRIVATE_FUNCTION_SPECIFIER = '_'
---@class BaseClass
---@operator call:self
---@field init fun(self, ...)
---@field super fun(self: self): table

---@param base? table
---@param init? fun(self, ...)
Expand All @@ -51,6 +52,45 @@ function Class.new(base, init)

instance.__index = instance

instance.super = function(object)
if object._superProxy then
return object._superProxy
end
local proxy = {}
local proxyMT = {
__index = function (obj, param)
if param == 'super' then
error('Cannot create proxy from a super proxy')
end
local objVal = rawget(object, param)
if objVal then
return objVal
end
return base and base[param]
end,
_base = base,
_isSuperProxy = true,
__newindex = object,
__add = base and base.__add,
__sub = base and base.__sub,
__mul = base and base.__mul,
__div = base and base.__div,
__mod = base and base.__mod,
__pow = base and base.__pow,
__unm = base and base.__unm,
__concat = base and base.__concat,
__eq = base and base.__eq,
__lt = base and base.__lt,
__le = base and base.__le,
__pairs = base and base.__pairs,
__ipairs = base and base.__ipairs,
__tostring = base and base.__tostring,
}
setmetatable(proxy, proxyMT)
object._superProxy = proxy
return proxy
end

local metatable = {}

metatable.__call = function(class_tbl, ...)
Expand Down
Loading