Navigation menu
Personal tools
Not logged in
Talk
Contributions
Create account
Log in
Namespaces
WoW
Talk
English
Views
Read
Edit
History
More
Search
Navigation
Home
Random page
Help using wiki
Editions
for WoW
for WildStar
for Solar2D
Documentation
for WoW
for WildStar
Reference
WoW
⦁ FrameXML
⦁ AddOns
⦁ API
⦁ WoW Lua
WildStar
⦁ AddOns
⦁ API
⦁ WildStar Lua
Engine
Tools
What links here
Related changes
Special pages
Page information
Site
Recent Changes
Editing
WoW:Object-oriented programming
(section)
Jump to navigation
Jump to search
Warning:
You are not logged in. Your IP address will be publicly visible if you make any edits. If you
log in
or
create an account
, your edits will be attributed to your username, along with other benefits.
Anti-spam check. Do
not
fill this in!
===== Metatables ===== Metatables are defined by the Lua documentation as "an ordinary Lua table that defines the behavior of the original value under certain special operations" [http://www.lua.org/manual/5.1/manual.html]. We want to control one of these special operations. Specifically, we want to control how the table accesses variables that do not exist. While this may not seem immediately logical, it is a simple trick that we can use to convince Lua of functions that are defined for all instances of the class. First, let's create the function. The function is created much like you would find any other function available. Normally, a function is created using the following syntax: function foo() -- Code block end In our case, we need the function to be a member of the class we are defining. Thus, it needs to be contained within the base table, which in our case, is called "Character." For the above example "isAllance()," we would want to create the function like this: function Character:isAlliance() -- Code block end Note the slight difference: We use a colon instead of a period here. This is typically used for non-static functions (functions which rely upon the state of the class, or the variables inside the instance of the class, to determine their operation). This is needed because we need to know the variable "race" inside our instance. This determines whether the function returns true or false. The use of this colon states that, when this function is called, a [[Lua Scope#Function-local Variables|function-local variable]] will be created. The variable will be named "self" and is a reference to the instance of the class. Thus, we can use the variable "self.class" to determine the class of that one particular character. The Lua reference manual states the following[http://www.lua.org/manual/5.1/manual.html]: :The colon syntax is used for defining methods, that is, functions that have an implicit extra parameter self. Thus, the statement ::function t.a.b.c:f (params) body end :is syntactic sugar for ::t.a.b.c.f = function (self, params) body end We still have one problem, though. The instance of our class. While it is created by the Character table, it is not actually Character table itself, thus if we do the following: local me = Character:new(); DEFAULT_CHAT_FRAME:AddMessage(me:isAlliance()); This will fail, because me:isAlliance is undefined (me.isAlliance is never created; only Character.isAlliance). This is where metatables come in. A metatable can tell a table where to find indexes that do not exist. Thus, we can use it to help find functions which appear to not exist. Specifically, we specify that the instance should look up unknown indexes in the table "Character," so that when it tries to look for me.isAlliance, and does not find it, it will proceed by searching for Character.isAlliance, which does exist. This is done via the metatable's "__index" field (note that is two underscores, not one). The __index field states that if a variable cannot be found, it will be searched for in the table specified by __index. Thus, we can do the following during creation: Character = {}; -- To create a class, we must make a table Character.__index = Character; -- Set the __index parameter to reference Character function Character:new() local self = {}; setmetatable(self, Character); -- Set the metatable so we used Character's __index -- Imbue the class return self; end function Character:isAlliance() -- Perform calculation end Now, every instance of Character also has a way to access isAlliance(). Thus, we only create one copy of the function, so we save a lot of memory, but every character has a way to access that function and use it appropriately. Even more usefully, if another addon later hooks Character.isAlliance(), you will find that all instances will use the new, hooked function. This way, we don't have to modify every instance of the class.
Summary:
Please note that all contributions to AddOn Studio are considered to be released under the Creative Commons Attribution-NonCommercial-ShareAlike (see
AddOn Studio Wiki:Copyrights
for details).
Submissions must be written by you, or copied from a public domain or similar free resource (see
AddOn Studio Wiki:Copyrights
for details).
Cancel
Editing help
(opens in new window)