I'm currently working on a module that allows JS-Like classes to be implemented easily in LUA
I've added the ability to extend classes but I'm having an issue with extending classes twice, it seems to be some sort of issue within the super constructor function that's causing a recursive call however I can't seem to figure out where the bug is coming from, any help would be appreciated
Module:
local ClassCreator = {}
ClassCreator.extends = {__extends = true}
local function modifyFnEnv(f, env)
local fEnv = getfenv(f)
for i,v in pairs(env) do fEnv[i] = v end
setfenv(f, fEnv)
end
local ClassMt = {
__call = function (self, ...)
local newClass = {}
setmetatable(newClass, {__index = self.prototype})
modifyFnEnv(newClass.constructor, {
self = newClass
})
newClass.constructor(...)
return newClass
end
}
local function makeClass(self, targs)
local Class = {
prototype = {}
}
setmetatable(Class, ClassMt)
local constructor, SuperClass = function() end, Class
for i,v in pairs(targs) do
if i == ClassCreator.extends then
SuperClass = v
setmetatable(Class.prototype, {__index = SuperClass.prototype})
elseif i == "constructor" then
constructor = v
else
Class.prototype[i] = v
end
end
if SuperClass ~= Class then
modifyFnEnv(constructor, {
super = SuperClass.prototype.constructor
})
end
Class.prototype.constructor = constructor
return Class
end
setmetatable(ClassCreator, {
__call = makeClass
})
return ClassCreator
Test Code:
local Class = require("Class")
local Human = Class {
constructor = function(name, age)
self.name = name
self.age = age
end,
describe = function(self)
return string.format(
"My name is %s and I am %d years old",
self.name,
self.age
)
end
}
local Programmer = Class {
[Class.extends] = Human,
constructor = function (name, age, yearsOfExperience)
super(name, age)
self.yearsOfExperience = yearsOfExperience
end,
describe = function(self)
return string.format(
"My name is %s and I am %d years old, I have %d years of experience",
self.name,
self.age,
self.yearsOfExperience
)
end
}
local LuaProgrammer = Class {
[Class.extends] = Programmer,
constructor = function (name, age, yearsOfExperience)
super(name, age, yearsOfExperience)
end,
describe = function(self)
return string.format(
"My name is %s and I am %d years old, I have %d years of experience in Lua",
self.name,
self.age,
self.yearsOfExperience
)
end
}
local John = Human("John", 35)
local JohnProgrammer = Programmer("John", 35, 5)
local JohnLuaProgrammer = LuaProgrammer("John", 35, 5)
print(John:describe())
print(JohnProgrammer:describe())
print(JohnLuaProgrammer:describe())
Expected output:
My name is John and I am 35 years old
My name is John and I am 35 years old, I have 5 years of experience
My name is John and I am 35 years old, I have 5 years of experience in Lua
Current output:
lua: src/test.lua:20: stack overflow
stack traceback:
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
...
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'constructor'
./src/Class.lua:17: in function 'Programmer'
src/test.lua:51: in main chunk
[C]: ?
CodePudding user response:
You can work on the popbob stack interval post index.
Example:
print(1)
print("2")
CodePudding user response:
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a noise.`);
}
}
class Dog extends Animal {
constructor(name) {
super(name); // call the super class constructor and pass in the name parameter
}
speak() {
console.log(`${this.name} barks.`);
}
}