Understanding metatables
From GMod Wiki
Lua: Understanding Metatables |
Description: | Explains Lua metatables |
Original Author: | Anders |
Created: | 1st December 2006 |
This article is a stub. You can help the GMod Wiki by expanding it. |
This article is far from completed... if you can help out that would be great!
The article might not be as clear as I wanted it to be, so if you have any suggestions please tell me on the article discussion page! --Anders 18:06, 1 December 2006 (GMT Standard Time)
Contents |
What are Metatables?
Metatables let you change the behavior of the data types available in Lua. They are heavily used by GMod to implement custom data types, such as Vectors, Angles, Players and so on. Metatables are very useful for object oriented programming.
In this article I will implement a custom data type for defining colors.
Metamethods
The available metamethods are:
- __add (LHS + RHS)
- __sub (LHS - RHS)
- __mul (LHS * RHS)
- __div (LHS / RHS)
- __mod (LHS % RHS)
- __pow (LHS ^ RHS)
- __unm (-RHS)
- __concat (LHS .. RHS)
- __len (#RHS)
- __eq (LHS == RHS)
- __lt (LHS < RHS)
- __le (LHS <= RHS)
- __index - Table access
- __newindex - Table assignment
- __call - Whenever the object is called like a function
- __tostring - Lets you decide what using tostring() on your object will return
Color library
This is the color library that I've written.
-- This is supposed to be saved as lua/includes/modules/color.lua module("color", package.seeall) -- Without package.seeall we would not be able to see any variables in the global scope (Msg etc) local mt = {} -- The metatable local methods = {} -- Methods for our color objects mt.__index = methods -- Redirect all key "requests" to the methods table -- Function for creating new color objects -- -- Usage: col = color.new() or -- col = color.new(red, green, blue, alpha) function new (r, g, b, a) local obj = {} -- This is the color object obj.r = r or 0 obj.g = g or 0 obj.b = b or 0 obj.a = a or 255 setmetatable(obj, mt) -- This is the magic that makes everything work return obj end -- Override tostring() return value, without this, using tostring() on a color object would just return "table: 0xDEADBEEF" function mt:__tostring () -- You see how I use self below? This is because I used ":". -- It is syntactic sugar for adding the self argument. You could have written -- "function mt.__tostring (self)", it does the same... absolutely no difference. return "Color: "..self.r.." "..self.g.." "..self.b..." "..self.a end -- Define the multiplication operator -- Example: col = col1 * col2 -- col = col * 2 function mt:__mul (m) local mr, mg, mb, ma if type(m) == "table" then -- Make sure it's a color object if getmetatable(m) == mt then -- Copy the colors from the other color mr = m:R() mg = m:G() mb = m:B() ma = m:A() else error("can only multiply colors with other colors or numbers") end else if type(m) == "number" then m = math.floor(m) mr = m mg = m mb = m ma = m else error("can only multiply colors with other colors or numbers") end self.r = math.Clamp(mr * self.r, 0, 255) self.g = math.Clamp(mg * self.g, 0, 255) self.b = math.Clamp(mb * self.b, 0, 255) self.a = math.Clamp(ma * self.a, 0, 255) end -- Define the division operator -- Example: col = col / col2 -- col = col / 2 function mt:__div (d) local dr, dg, db, da if type(d) == "table" then -- Make sure it's a color object if getmetatable(d) == mt then -- Copy the colors from the other color dr = d:R() dg = d:G() db = d:B() da = d:A() else error("can only multiply colors with other colors or numbers") end else if type(d) == "number" then d = math.floor(d) dr = d dg = d db = d da = d else error("can only multiply colors with other colors or numbers") end self.r = math.Clamp(dr / self.r, 0, 255) self.g = math.Clamp(dg / self.g, 0, 255) self.b = math.Clamp(db / self.b, 0, 255) self.a = math.Clamp(da / self.a, 0, 255) end
See Also
- Metamethods Tutorial (Lua Users Wiki): http://lua-users.org/wiki/MetamethodsTutorial