How can multiple inheritance be achieved in Codea?
If I wanted class C to inherit both class A and B, what should I do?
i use this (not sure how othodox it is…)
-- this is to grab fields from another class
function mixin(target,source,field)
local fields = field
if type(fields) == "string" then fields = {field} end
for i,key in ipairs(fields) do
if type(key) ~= "string" then error("mixin must have only string(s) for field") end
local v = source[key]
if v == nil then error("field '"..key.."' is nil") end
target[key] = v
end
end
so it could be:
C = class(A)
mixin(C, B, B)
however it will work only for functions directly declared in B, not for the functions that B may inherit from class D if B = class(D). Because D keys are not in B, they are found for b= B() instances, and only after you’ve called them for the first time.
@Ignatz I was wondering if there is a component based example where Class C would be defined as a descendant of both classes A and B, without classes A or B knowing anything about each other. Is it possible to do something like:
C = class(A, B)
Then class C can be initialized with the member variables inherited from both its parents, A and B?
@the_dude- you can kludge it as below, by having a parent class A, and defining the sub classes as tables instead of classes. Then you can pass the sub classes to A and it can copy their functions into itself.
But I think a better component approach is shown in the thread I linked above.
function setup()
d=A("test case",B)
d:a()
d:b()
print("B variable is "..d.tag)
end
A=class()
function A:init(name,c)
self.name=name
if c then
for key,val in pairs(c) do
self[key]=val
end
end
end
function A:a()
print("A prints "..self.name)
end
B={}
function B:b() print("B prints "..self.name) end
B.tag="BB"
What about an edit to Codea’s classes?
-- Class.lua
-- Compatible with Lua 5.1 (not 5.0).
function class(...)
local arg = {...}
local c = {} -- a new class instance
c._bases = {}
for id, base in ipairs(arg) do
if type(base) == 'table' then
-- our new class is a shallow copy of the base class!
for i,v in pairs(base) do
c[i] = v
end
c._bases[#c._bases + 1] = base
c._base = base
end
end
-- the class will be the metatable for all its objects,
-- and they will look up their methods in it.
c.__index = c
-- expose a constructor which can be called by <classname>(<args>)
local mt = {}
mt.__call = function(class_tbl, ...)
local obj = {}
setmetatable(obj,c)
if class_tbl.init then
class_tbl.init(obj,...)
else
-- make sure that any stuff from the base class is initialized!
if base and base.init then
base.init(obj, ...)
end
end
return obj
end
c.is_a = function(self, klass)
local m = getmetatable(self)
while m do
if m == klass then return true end
m = m._base
end
return false
end
setmetatable(c, mt)
return c
end
That should let you call A = class(B, C)
and have A inherit functions from both B and C.
There’s a reason why C++ and Java don’t have multiple inheritance, why would you need it? Inheritance can bring an awful lot of baggage - especially if you have a complex hierarchy. Modern thinking tends to favour a component based approach instead - KISS!