Home > Software engineering >  Issue within my custom Class module - LUA
Issue within my custom Class module - LUA

Time:07-27

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.`);
  }
}
  • Related