Reputation: 33
I'm aware there are a few questions about implementing OOP in Lua on this site, however, this one is a bit different (at least compared to what I found).
I'm trying to create a class called "human", and make it so objects created with the "new" constructor of "human", inherit everything inside human except it's constructor. However, I also don't want to be able to use methods inside of human, on human. So whatever's inside the human class, is only passed to created objects. Here's an example:
-- "Human" class
human = {}
function human.new(name)
local new = {} -- New object
-- Metatable associated with the new object
local newMeta =
{
__index = function(t, k)
local v = human[k] -- Get the value from human
print("Key: ", k)
if type(v) == "function" then -- Takes care of methods
return function(_, ...)
return v(new, ...)
end
else
return v -- Otherwise return the value as it is
end
end
}
-- Defaults
new.Name = name
new.Age = 1
return setmetatable(new, newMeta)
end
-- Methods
function human:printName()
print(self.Name)
end
function human:setAge(new)
self.Age = new
end
-- Create new human called "bob"
-- This works as expected
local bob = human.new("Bob")
print(bob.Name) -- prints 'Bob'
bob:printName() -- prints 'Bob'
bob:setAge(10) -- sets the age to 10
print(bob.Age) -- prints '10'
-- But I don't want something like this allowed:
local other = bob.new("Mike") -- I don't want the constructor passed
-- I'd also like to prevent this from being allowed, for "human" is a class, not an object.
human:printName()
So creating the object with human.new("Bob")
works fine, but it also passes the constructor, and I can still use the object methods on the class. I'm very new to the concept of OOP, so I'm sorry if this was a horrible question. But if anyone could help, I'd appreciate that.
Upvotes: 2
Views: 1618
Reputation: 1595
I have run into the same issue before. You need two tables. One for object methods and one for class methods. Set the metatable of constructed objects to the object method table. For example:
local Class = {}
local Object = {}
Object.__index = Object
function Class.new()
return setmetatable({}, Object)
end
setmetatable(Class, {__call = Class.new})
function Object.do()
...
end
return Class
And use it
Class = require('Class')
local obj = Class.new() -- this is valid
obj.do() -- this is valid
obj.new() -- this is invalid
Class.do() -- this is invalid
Upvotes: 6