Scope: local vs global

From Riftui Wiki

Jump to: navigation, search

When creating an addon, it is vitally important to remember the scope of variables, functions, even the addon itself. Assigning the word "local" in front of these changes the scope from global, where the variable or function can be accessed and modified by other addons, to local, and therefore only accessable and modifiable by the addon. Consider the following two examples of a variable.

Contents

Variables

name = "Myrroddin"
local name = "Myrroddin"

The first instance of name can be seen by the entire addon framework, including other addons. It is also a poorly named variable. If two addons, MyAddon and YourAddon both used the same name for a variable, they can, and most likely will conflict. Even if one of those addons used the correct syntax and made the variable local, depending on when it is called or defined, it can still be overwritten by the global version.

It is always recommended to define all variables as local.

Functions

The same logic also applies to functions.

function SomeFunction()
local function SomeFunction()

The first is bad, and should only be used if it is expressly desire to have the function be available everywhere to all addons, while the second is the correct use. There is a best practice for defining a function with global scope. Most library files are written this way, give or take changes to the naming structure. An addon that defines functions that are available to other addons can be written this way, but the API offers a better solution, discussed after the global function examples.

Global Addons

MyAddon = {} -- define the addon globally
MyAddon:SomeFunction()

There are two alternate methods to define an addon globally if speed becomes necessary. For small addons and library files, you can use these methods, but you should test to see if there is any efficiency gain. We are using the global variable _G (underscore and capital G) to copy a local variable into the global namespace. The methods are identical in functionality.

local MyAddon = {} -- speed reference
_G.MyAddon = MyAddon
local MyAddon = {}
_G["MyAddon"] = MyAddon

Local Addons

Whenever possible, make your addons local in scope. It reduces global namespace clutter, optimizes your code, avoids conflicts, and makes your code easier to debug. Remember: you will still have to define all variables and functions locally. If your addon has only one Lua file, you only need one line at the top of your file.

local MyAddon = {}
local name = "Myrroddin"
local function PrintName()
    Print(name)
end
function MyAddon:PrintAgain() -- function is local because the addon is local
    Print(name)
end

However, many addons have multiple Lua files, and sometimes you need to access what you create in one file in a separate file. For that, we will use the addon private table. The addon private table is actually two tables, sharable amongst all related files. Being tables, you can assign any data to them. Just as with any other variable, you can name them however you wish.

FileOne.lua

local MyAddon, privateTable = ... -- write this at the top of every file
privateTable.name = "Myrroddin"
MyAddon:SomeFunction()
    -- do something
end

FileTwo.lua

local MyAddon, privateTable = ...
Print(privateTable.name) -- prints "Myrroddin"
MyAddon:SomeFunction() -- call function defined in FileOne.lua

FileThree.lua

local _, privateTable = ... -- we aren't using the MyAddon variable
privateTable.gender = "Male"

Something to keep in mind: while it is theoretically possible to define data to the addon private table in any file, it is a good practice to define the data as early as possible. That means you can define the gender in FileThree.lua and access it in FileOne.lua, but it is not recommended because FileOne.lua loads first. If you are in doubt, test, test test!

Most authors use the addon private table to create and define their localization strings, therefore making them accessible to any file in the addon's structure. However, as mentioned, you can assign anything to the table that any normal table could contain. Of course, there is no point in assigning data to the private table that does not need to be shared through files. Use a local table in that case.

How to Access the Private Table from any Addon

Rift's API offers a tool to retrieve the private table of any addon. A useful idea might be to create a frame in MyAddon and be modifiable in YourAddon.

MyAddon.lua

local MyAddon, PT = ...
PT.Context = UI.CreateContext("context")
PT.Frame = UI.CreateFrame("Frame", PT.Context)

YourAddon.lua

local detail = Inspect.Addon.Detail("MyAddon")
detail.data.Frame:SetVisible:(false) -- hide the frame created in MyAddon.lua, but in YourAddon.lua!!

You will want to be extremely careful with using Inspect.Addon.Detail in such a fashion, as you can easily break another addon in this manner. Exercise caution!

Personal tools
Namespaces
Variants
Actions
Menu
Wiki
Toolbox