generic image
Processing...
  • Games
  • Catalog
  • Develop
  • Robux
  • Search in Players
  • Search in Games
  • Search in Catalog
  • Search in Groups
  • Search in Library
  • Log In
  • Sign Up
  • Games
  • Catalog
  • Develop
  • Robux
   
ROBLOX Forum » Game Creation and Development » Scripting Helpers
Home Search
 

Re: Metatables

Previous Thread :: Next Thread 
Solotaire is not online. Solotaire
Joined: 30 Jul 2009
Total Posts: 30356
02 Mar 2014 10:25 AM
To my understanding, metatables are the closest thing RBX.Lua has to allowing us to create classes. I'm trying to figure out how to instantiate new objects with it. If I assign a metatable, the values for the table appear to remain nil. This might be an error with my setmetatable() use. Thanks for the help. I've provided a short piece of code to explain what I'm talking about.

local Fighter = {
Name = "Fighter";
Level = "1";
TotalExperience = 0;
}

local myfighter = setmetatable({}, Fighter)

myfighter.Level = 99

for k,v in pairs(myfighter) do
print(k, v) -- only prints "Level 99", not name or experience
end

print(myfighter.Name) -- returns nil
Report Abuse
blobbyblob is not online. blobbyblob
Joined: 29 Oct 2008
Total Posts: 12165
02 Mar 2014 10:33 AM
You're going about it a little wrong. Metatables are no good for data. They'll only work for functions.

local FighterDataMemberDefaults = {
Name = "Fighter";
Level = 1;
TotalExperience = 0;
}
local FighterMetatable = {
__index = function(t, i)
return FighterDataMemberDefaults[i];
end;
}

local myfighter = setmetatable({}, FighterMetatable);
myfighter.Level = 99;

for k, v in pairs(myfighter) do
print(k, v); --Still only prints "Level 99", but...
end

print(myfighter.Name); --prints Fighter
print(myfighter.TotalExperience); --prints 0



Metatables are a little strange a concept. I'll follow up this post with another method of doing classes in Lua using metatables. I just don't wanna make the post overwhelmingly long.
Report Abuse
Solotaire is not online. Solotaire
Joined: 30 Jul 2009
Total Posts: 30356
02 Mar 2014 10:54 AM
Hm, alright. I think I can deal with having to access each value independently. Thanks for the help.
Report Abuse
blobbyblob is not online. blobbyblob
Joined: 29 Oct 2008
Total Posts: 12165
02 Mar 2014 10:58 AM
--Create scope level. Once this "do" block is left, no one
--can access FighterDataDefaults or FighterMetatable.
do

--All data for all classes is stored here.
local Data = {};

local FighterDataDefaults = {
Name = "Fighter";
Level = 1;
Experience = 0;
}

local FighterMetatable = {
__index = function(t, i)
--Return the data if the object has it.
--If the object doesn't have it, return the default.
return Data[t][i] or FighterDataDefaults[i];
end;

__newindex = function(t, i, v)
Data[t][i] = v; --Set the data in the data table.
end;
}

function NewFighter()
local o = {};
Data[o] = {}; -- Create a new entry for this instance's data.
return setmetatable(o, FighterMetatable);
end
end

local f = NewFighter();
f.Name = "Brick Hardpec";
local y = NewFighter();
y.Name = "Punches Malone";
print(f.Name); --Brick Hardpec
print(y.Name); --Punches Malone
print(f.Level); --1
print(f.Experience); --0

for i, v in pairs(f) do
print(i, v); --prints nothing. The data members are hidden.
end




So! Why is this a good approach? Mainly, data sanitation.

If you want to make sure that people don't submit numbers into your "Name" field, you can do that in the __newindex function. Same goes for strings into your experience field.

Furthermore, if someone types NewFighter().BicepSize = 4, you can totally make that just return an error that says "BicepSize is not a valid member of Fighter".


One final point, which I didn't want to include in my code because it's a little confusing: the Data table should have weak keys. This prevents a ton of Fighter instances from building up when you've already gotten rid of them in other parts of your code.
If you wanna take my word for it, just replace the Data={} line with this:
Data = setmetatable({}, {__mode="k"});
It might be worth googling "Lua weak tables" to figure out what's going on when you do that.
Report Abuse
Solotaire is not online. Solotaire
Joined: 30 Jul 2009
Total Posts: 30356
02 Mar 2014 12:59 PM
Wow, that's pretty helpful.

I should be able to metatables to create subclasses, correct? Or is there a problem with including metatables when I want to create them? If so, is there a way to use multiple inheritance instead?

Something like this, I guess:

local classDataDefaults = {
-- things all classes will have
ClassName = "";
Level = 1;
Experience = 0;
}

local classDataMetatable = {
-- index/newindex functions
}

local mageDataDefaults = {
-- "subclass"; includes class defaults + specifics
setmetatable({}, classDataMetatable);
Mana = 100;
}

local mageMetatable = {
--index/newindex functions
}
Report Abuse
blobbyblob is not online. blobbyblob
Joined: 29 Oct 2008
Total Posts: 12165
02 Mar 2014 01:52 PM
Your syntax is a little off, but yeah, that's the general idea. If you can't find the field/function in Mage, then you'd search the class above using metatables, namely Fighter (or class, or whatever this is a subclass of).
Report Abuse
Solotaire is not online. Solotaire
Joined: 30 Jul 2009
Total Posts: 30356
02 Mar 2014 04:40 PM
What should I do to fix it? I went to the lua-users site and found their way of implementing a subclass, but I'm not sure I understand what they have.


Things I noticed on the page were:

local newclass = {}
setmetatable(newclass, {__index = baseclass})

and this:

function newclass:create()
local new_inst = {} -- the new instance
setmetatable( new_inst, newclass_mt) -- all instances share the same metatable
return new_inst
end

The function is similar to the "NewFighter" function you made, so I think this is just another way to implement that. For the first part, is that the syntax I'm looking for?

I think that would give me this:
local mageDataDefaults = {
-- "subclass"; includes class defaults + specifics
setmetatable({}, {__index = classData};
Mana = 100;
}

The site also didn't have different areas for default values and the index/newindex functions (in fact, they appear to just send in __index as a value at random places), so part of my confusion might be due to that.
Report Abuse
Previous Thread :: Next Thread 
Page 1 of 1
 
 
ROBLOX Forum » Game Creation and Development » Scripting Helpers
   
 
   
  • About Us
  • Jobs
  • Blog
  • Parents
  • Help
  • Terms
  • Privacy

©2017 Roblox Corporation. Roblox, the Roblox logo, Robux, Bloxy, and Powering Imagination are among our registered and unregistered trademarks in the U.S. and other countries.



Progress
Starting Roblox...
Connecting to Players...
R R

Roblox is now loading. Get ready to play!

R R

You're moments away from getting into the game!

Click here for help

Check Remember my choice and click Launch Application in the dialog box above to join games faster in the future!

Gameplay sponsored by:
Loading 0% - Starting game...
Get more with Builders Club! Join Builders Club
Choose Your Avatar
I have an account
generic image