简体   繁体   中英

OOP in Lua - Creating a class?

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.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM