So I’ve been working with C++ in my courses, and I feel pretty confident in the idea of classes and private/public, so when I figured out how to do it in roblox I jumped right on it. for the most part, this all makes sense. The video, by crockpot dev, explains pretty well.
however, a few questions arose for me. One, from my understanding, the table (self) that is always getting returned is an empty table, only containing class methods if I’m not mistaken. So how is he able to index this ‘hidden’ table using that table?
Secondly, this is rather minor but by doing this you would always have to call methods using : because you need self, unless you pass it as a parameter?
local Table = {}
local newMeta = {}
newMeta.__index = newMeta
newMeta.__metatable = "you cant do that!"
newMeta.__newindex = function(_,_,_)
print("you cant do that either!")
end
local hidden = {}
function Table.new()
local self = {}
local priv = {}
priv.value = 5
hidden[self] = priv
return setmetatable(self,newMeta)
end
function newMeta:PrintValue()
print(hidden[self].value)
end
return Table
I’m not quite sure what you mean by this question.
A table in Lua is only equal to itself, despite what it might be like in other programming languages. Even if two tables are both empty, they will have different memory addresses and thus have different hashes when you use them in a hashmap (dictionary).
When you call the constructor method .new, it will use the just-generated object as the index to store a separate “private” table inside hidden. Since the object itself is always passed as self for method calls, you can use it to retrieve the original private table because it is the same exact table that encoded it into hidden, so you can directly index using it.
By convention, instance methods in Lua are always called with the colon operator to distinguish it from a class method. BUT, fundamentally it’s the same and the colon operator is just a quality-of-life shortcut to automatically insert the object as the first parameter for a class method. In other words, these two are the same:
object.Method(object, ...)
object:Method(...)
And using colons to define class methods follow the same pattern:
--these two are the same, BUT the bottom one makes it
--harder to annotate the type of the object :(
export type class = typeof(setmetatable({}, class))
function class.Method(self: class, ...)
return print(self)
end
function class:Method(...)
local self: class = self::any
return print(self)
end
ok I think this makes sense, the big problem I had was more of a syntactical problem, I know you can index tables using strings and numbers, but I was unsure about using a table I guess.
local newTable = {name = Table, value = 10}
local newTable = {{} = "ABC"}
I know this is a poor example but, what I mean is that the specific memory address of the table used in the latter example can be used as an index?
The table type implements associative arrays. An associative array is an array that can be indexed not only with numbers, but also with strings or any other value of the language, except nil .
So you can do something like this:
local a = {}
local b = {}
a[b] = 1
print(a[b]) --> 1
print(a[{}]) --> nil