Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

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.

Tagged:

Comments

  • Posts: 2,020

    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)}
    
  • edited September 2015 Posts: 557

    @yojimbo2000, you super-smart.

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

  • edited September 2015 Posts: 2,020

    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!

  • edited September 2015 Posts: 435
    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"}
    
  • admirable´╝înice example

  • IgnatzIgnatz Mod
    Posts: 5,396

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

  • 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
    
Sign In or Register to comment.