10
\$\begingroup\$

I've discovered (and written) a way to object oriented programming in lua in a functional fashion instead of the standard metatable method. It carries much more functionality (no pun intended) but I'm afraid it might dent performance. My goal is to experiment with servers written in lua and I wanted to use this OOP solution. Anyways here's my class.lua which holds the functions for creating new objects and subclasses.

local classes = setmetatable({}, {__mode = "k"}) -- Allow the GC to empty this as needed.
function class(f, super)
 classes[f] = {super = super}
end
function new(f, obj, ...)
 local fenv = getfenv(f)
 if type(obj) ~= "table" then
 error("bad argument: expected table, got " .. type(obj) , 2)
 end
 if classes[f] and classes[f].super then
 new(classes[f].super, obj, ...)
 local super = obj
 obj = setmetatable({}, { __index = super })
 obj.super = super
 else
 setmetatable(obj,{__index = fenv})
 end
 obj.this = obj
 setfenv(f, obj)
 f()
 setfenv(f, fenv)
 if obj.init then
 obj.init( ... )
 end
 return obj
end

Usage is fairly simple. Take the following example:

function Person()
 local privateVar = math.random()
 age, name, gender = nil, nil, nil
 function init(age, name, gender)
 this.age = age
 this.name = name
 this.gender = gender
 end
 function getPrivateVar()
 return privateVar
 end
end

And to create the object

obj = new(Person, {}, "John", 30, "male")

Subclassing is also simple

function Female()
 function init(name, age)
 super.init(name, age, "female")
 end
end
class(Female, Person)

Note that you only have to call a function to make something a class if you want to subclass.

When you call new, you pass in the class, object, and arguments. The object's metatable is set to have an index of the class's original environment. Then the super is determined and created. Then the class function is run to create all instance values. Next, init is called.

One advantage of this over metatables are that other code can't change the class and have it change all instances of that class that already exist and that will exist. Now the only way to do something like that is to swizzle and hack around in environments to make sure all references to the class refer to the hacker's dummy class.

On top of that, it supports private variables. Just declare them locally in your class function and you're good to go.

But I'm wondering if the fact that it creates all the instance methods once for every instantiation is going to cause performance problems. Will this eat memory? What can go wrong here?

Also, there's an issue. While this supports multiple inheritance, if you call a super method, and the super calls a method, it will call the method of the super class, not the instantiated class. Any ideas how to make it call from the instantiated class?

Caridorc
28k7 gold badges54 silver badges137 bronze badges
asked Mar 17, 2013 at 21:22
\$\endgroup\$

1 Answer 1

4
\$\begingroup\$

Even though this kind of inheritance is perfectly valid example of OOP designing in language like Lua; it is considered a bad practice of programming.

According to Programming in Lua on Object-Oriented Programming.

This kind of function is almost what we call a method. However, the use of the global name Account inside the function is a bad programming practice.

  1. This function will work only for this particular object.
  2. Even for this particular object the function will work only as long as the object is stored in that particular global variable; if we change the name of this object, withdraw does not work any more.

The example they've used to depict is also quite to the point and small.

You should also take a look at how they've explained creation of classes; their inheritance; public, private and protected datatypes/variables and many other OOP concepts using metamethods and tables depending on their usage.

Here's the index of OOP concepts incorporated in Lua.

Useful Links

answered Mar 18, 2013 at 14:57
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.