From 834a400f078780b442e58a574943755c89c36b30 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Mon, 28 Sep 2020 18:40:47 +0300 Subject: [PATCH 1/7] fix(pl.class): Correct inheritance direction for class(base, nil, input) --- lua/pl/class.lua | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/lua/pl/class.lua b/lua/pl/class.lua index 49246ee3..1a78daac 100644 --- a/lua/pl/class.lua +++ b/lua/pl/class.lua @@ -117,9 +117,9 @@ local function _class_tostring (obj) return str end -local function tupdate(td,ts,dont_override) +local function populate(td,ts) for k,v in pairs(ts) do - if not dont_override or td[k] == nil then + if td[k] == nil then td[k] = v end end @@ -136,13 +136,13 @@ local function _class(base,c_arg,c) base = c._base else c = c or {} + c._base = base end if type(base) == 'table' then - -- our new class is a shallow copy of the base class! - -- but be careful not to wipe out any methods we have been given at this point! - tupdate(c,base,plain) - c._base = base + -- Shallow-copy methods from the base class into our target class being + -- careful not to wipe out any methods explicitly passed as input + populate(c,base) -- inherit the 'not found' handler, if present if rawget(c,'_handler') then mt.__index = c._handler end elseif base ~= nil then From 4a7f2066d9da8579d49fa62c57fc1075bc8bab57 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Mon, 28 Sep 2020 20:04:03 +0300 Subject: [PATCH 2/7] test(pl.class): Add test units for alternate class inheritance syntax --- tests/test-class5.lua | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 tests/test-class5.lua diff --git a/tests/test-class5.lua b/tests/test-class5.lua new file mode 100644 index 00000000..d6057033 --- /dev/null +++ b/tests/test-class5.lua @@ -0,0 +1,26 @@ +-- Another syntax for creating a class inheriting methods from a base class +-- while also using a table for input methods. +local class = require('pl.class') + +local A = class({ + _init = function (self) + self.info = "A" + end + }) + +local B = class(A, nil, { + _init = function(self) + self:super() + self.info = self.info .. "B" + end + }) + +local C = class(B, nil, { + _init = function(self) + self:super() + self.info = self.info .. "C" + end + }) + +local foo = C() +assert(foo.ino == "ABC") From 29a296a9bbe88f2fa1b7bac065391e5573d6d3cb Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 29 Sep 2020 00:15:19 +0300 Subject: [PATCH 3/7] chore(pl.class): Add check for bad input to alternate class instantiation --- lua/pl/class.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/lua/pl/class.lua b/lua/pl/class.lua index 1a78daac..5728d18f 100644 --- a/lua/pl/class.lua +++ b/lua/pl/class.lua @@ -132,6 +132,7 @@ local function _class(base,c_arg,c) -- can define class by passing it a plain table of methods local plain = type(base) == 'table' and not getmetatable(base) if plain then + if type(c) == "table" then error("base is not a class",3) end c = base base = c._base else From e5fea09958a39ec4f89c240134a13f7f6c869168 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 29 Sep 2020 11:12:15 +0300 Subject: [PATCH 4/7] docs(pl.class): Clarify what arguments to class constructor are --- lua/pl/class.lua | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lua/pl/class.lua b/lua/pl/class.lua index 5728d18f..e669e416 100644 --- a/lua/pl/class.lua +++ b/lua/pl/class.lua @@ -45,15 +45,15 @@ end --- initializes an __instance__ upon creation. -- @function class:_init --- @param ... parameters passed to the constructor +-- @param ... input parameters passed to the constructor -- @usage local Cat = class() -- function Cat:_init(name) -- --self:super(name) -- call the ancestor initializer if needed -- self.name = name -- end -- --- local pussycat = Cat("pussycat") --- print(pussycat.name) --> pussycat +-- local pussycat = Cat("sparkles") +-- print(pussycat.name) --> sparkles --- checks whether an __instance__ is derived from some class. -- Works the other way around as `class_of`. It has two ways of using; @@ -126,10 +126,10 @@ local function populate(td,ts) end local function _class(base,c_arg,c) - -- the class `c` will be the metatable for all its objects, - -- and they will look up their methods in it. + -- the input table `c`, if provided, will become the the class object local mt = {} -- a metatable for the class to support __call and _handler - -- can define class by passing it a plain table of methods + -- alternatively if base is not a class and no input table c is provided + -- then base is used as a template and converted to a class object local plain = type(base) == 'table' and not getmetatable(base) if plain then if type(c) == "table" then error("base is not a class",3) end @@ -210,9 +210,9 @@ end -- The second form creates a variable `Name` in the current environment set -- to the class, and also sets `_name`. -- @function class --- @param base optional base class --- @param c_arg optional parameter to class constructor --- @param c optional table to be used as class +-- @param base optional base class to derive from +-- @param c_arg optional parameter passed to class constructor +-- @param c optional table of methods to be used populate the class local class class = setmetatable({},{ __call = function(fun,...) From 3d0b413fa897a160ee922c1785def0ccc4d9a0bd Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 29 Sep 2020 16:45:41 +0300 Subject: [PATCH 5/7] Revert "pl.class can be used more conveniently from Moonscript" This reverts commit 552807fcf16b58fb01abf3659764eff35b3c65cc. --- lua/pl/class.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/lua/pl/class.lua b/lua/pl/class.lua index e669e416..f97c0409 100644 --- a/lua/pl/class.lua +++ b/lua/pl/class.lua @@ -154,7 +154,6 @@ local function _class(base,c_arg,c) setmetatable(c,mt) if not plain then if base and rawget(base,'_init') then c._parent_with_init = base end -- For super and inherited init - c._init = nil end if base and rawget(base,'_class_init') then From e0ec7e9ef9e406699120237d14d0609847e21be6 Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 29 Sep 2020 00:51:08 +0300 Subject: [PATCH 6/7] TMP: dev debug stuff --- tests/test-class5.lua | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/tests/test-class5.lua b/tests/test-class5.lua index d6057033..d696901c 100644 --- a/tests/test-class5.lua +++ b/tests/test-class5.lua @@ -2,25 +2,35 @@ -- while also using a table for input methods. local class = require('pl.class') +-- From a plain table of methods local A = class({ + info = "foo", _init = function (self) self.info = "A" end }) +-- From a plain table of methods, inherit from a base local B = class(A, nil, { _init = function(self) - self:super() + print("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF") + -- self._base._init(self) + -- self:super() self.info = self.info .. "B" end }) -local C = class(B, nil, { - _init = function(self) - self:super() - self.info = self.info .. "C" - end - }) +-- -- From a base plus a plain table +-- local C = class(B, nil, { +-- -- local C = class({ +-- -- _base = B, +-- _init = function(self) +-- -- self._base._init(self) +-- -- self:super() +-- self.info = self.info .. "C" +-- end +-- }) -local foo = C() -assert(foo.ino == "ABC") +local foo = B() +print("DEBUG:"..foo.info) +assert(foo.info == "AB") From b41e06112289a06c235604bb2dfc96103f0ad2cd Mon Sep 17 00:00:00 2001 From: Caleb Maclennan Date: Tue, 29 Sep 2020 17:05:06 +0300 Subject: [PATCH 7/7] TMP: messing with testing different syntaxes --- tests/test-class-mix.lua | 74 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 tests/test-class-mix.lua diff --git a/tests/test-class-mix.lua b/tests/test-class-mix.lua new file mode 100644 index 00000000..bc5595c5 --- /dev/null +++ b/tests/test-class-mix.lua @@ -0,0 +1,74 @@ +_G.___w = false + +local class = require("pl.class") +local tablex = require("pl.tablex") + +local function subclass_hack (base, model) + return tablex.update(class(base), model) +end + +-- print("duck") +_G.___w = "foo" +local foo = class({ + -- attr = "original base", + _init = function (self) + print("Init foo class") + self.attr = "foo" + end, + finish = function (self, arg) + print("Finish foo class "..arg.." as "..self.attr.."\n") + end + }) + +_G.___w = "bar" +local bar = class(foo, nil, { + _init = function (self, arg) + print("Init bar class") + self:super(arg) + self.attr = "bar" + end + }) + +_G.___w = "baz" +local baz = class(foo) +function baz:_init (arg) + print("Init baz class") + self:super(arg) +end + +_G.___w = "qiz" +local qiz = subclass_hack(foo, { + attr = "qiz", + _init = function (self, arg) + print("Init qiz class") + self:super(arg) + end +}) + +_G.___w = "zar" +local zar = class({ + _base = foo, + _init = function (self, arg) + print("Init zar class") + self._base._init(self, arg) + -- self:super(arg) + self.attr = "zar" + end +}) + +-- Base class works as expected +foo():finish("1st") + +-- This does *not* work as expected, it functions as an instance of foo +bar():finish("2nd") + +-- This syntax works, its just cumbersome +local c = baz() +c.attr = "baz" +c:finish("3rd") + +-- This hack to do what I expected pl.class to do in the bar class +qiz():finish("4th") + +-- This gets the job done, but there is no super() function available +zar():finish("5th")