Function to Write Inits Faster

A lot of times when writing the init for a class, I find myself setting up all these properties in the form:

function TestClass:init(a, b, c)
    self.a=a
    self.b=b
    self.c=c

Is there any way to write a function or have something so that I don’t continue to keep on doing this?

I’ve fooled around with loadstring, but due to loadstring not being able to access my local variables, this is seeming harder to do than I had originally thought.

Thanks.

admirable?nice example

I applaud the ingenuity of some of the suggestions, but personally, I think the original code is the clearest and simplest.

A few ideas:

  1. Use class inheritance. If you have lots of similar game objects inherit from a common “entity” class, then you can sidestep lots of code repetition.

  2. Pass a table of keys to the class, and then copy the table:

MyClass = class()

function MyClass:init(t)
  for k,v in pairs(t) do
    self[k]=v
  end
end

MyInstance = MyClass{x = 20, y = 40, color = color(128,128)}

@yojimbo2000, you super-smart.

One obstacle is that you can’t tell anything about the necessary init properties that way.

Yeah, number 2 is super lazy, I wouldn’t really recommend it. I do like using tables of keys though. It’s nice to check if a key has been supplied and to throw in some defaults if it isn’t eg self.color = t.color or color(255) or whatever. I love how you can use or like that to catch nil values.

You could do:

MyClass = class()

local defaults = {
   x = 10,
   y = 30,
   z = 40,
   colour = color(130,12,38),
   somethingElse = true
}

function MyClass:init(t)
  for k,v in pairs(defaults) do
    self[k]= t[k] or v
  end
end

MyInstance = MyClass{x = 20, y = 40, color = color(128,128), otherOptions = "will be ignored"}

@LoopSpace What about booleans? If the default is true, then it’ll ignore if you pass in false.

@yojimbo2000 @loopspace Thanks for the ideas!

MyClass = class()

local defaults = {
   x = 10,
   y = 30,
   z = 40,
   colour = color(130,12,38),
   somethingElse = true
}

function MyClass:init(t)
  t = t or {}
  for k,v in pairs(defaults) do
    if t[k] ~= nil then
        self[k]= t[k]
    else
        t[k] = v
    end
  end
end

MyInstance = MyClass{x = 20, y = 40, color = color(128,128), otherOptions = "will be ignored"}

Hi @time4coding,

Somewhat related to this maybe, I’ve been experimenting with a way to auto-generate class members and their setters and getters, e.g.:

Enemy = class()
generateClassMember(Enemy "position")
generateClassMember(Enemy "alive", true)

The function implementation below generates a:
getPosition()
setPosition()
hasPosition()
getAlive()
setAlive()
hasAlive()
isAlive() – As is a boolean

Implementation is added below…

Trouble is, as mentioend above, you don’t get any IDE hints, and it probably obfuscates more that it helps!

(Note: typeCheck() just err… checks the type!))

Brookesi

local function generateClassMember(obj, member, default)

    typeCheck(member, "string")
    local function firstToUpper(str)

        return (str:gsub("^%l", string.upper))
    end

    local function checkFunction(obj, func)

        if (obj[func] and obj[func] ~= func) then
            error("Object has different: " .. func .. " function already")
        end
    end

    local suffix = firstToUpper(member)

    local setter = "set" .. suffix
    local setterFunc = function(self, value)
        self[member] = value
    end
    checkFunction(obj, setterFunc)
    obj[setter] = setterFunc

    local getter = "get" .. suffix
    local getterFunc = function(self)
        return self[member]
    end
    checkFunction(obj, getterFunc)
    obj[getter] = getterFunc

    local has = "has" .. suffix
    local hasFunc = function(self)
        return self[member] ~= nil
    end
    checkFunction(obj, hasFunc)
    obj[has] = hasFunc

    if (obj[member] and type(obj[member]) == "boolean") then
        local is = "is" .. suffix
        local isFunc = function(self)
            return self[member]
        end
        checkFunction(obj, isFunc)
        obj[is] = isFunc
    end

    if (default) then
        obj[member] = default
    end
end