Tutorials:Lua:ObjectOriented

From Cheat Engine
Revision as of 00:36, 28 May 2018 by Jgoemat (talk | contribs) (Added first part of LUA OO tutorial)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Calling Notation

The first thing to understand is that you can create functions on your tables. Think of a simple table for a rectangle with a length and width and a function that calculates the area. You can go ahead and run this script in CE (go to Memory Viewer and hit `CTRL+L` to open the Lua Engine)

local rect = { length = 7, width = 9 }
function calculateArea(tbl)
  return tbl.length * tbl.width
end
print('Width: '..tostring(calculateArea(rect)))


Let's look at creating the function *on the table*. This helps avoid naming collisions and keeps the global namespace clean. Here's an example up front showing how that works:

local rect = { length = 7, width = 9 }

function rect.calculateArea(tbl) -- `.` specifies object as argument
  return tbl.length * tbl.width
end

function rect:calculateArea2() -- `:` creates assumed 'self' first argument
  return self.length * self.width
end

rect.calculateArea3 = function(tbl)
  return tbl.length * tbl.width
end


-- need to pass table with `.`
print('Area: '..tostring(rect.calculateArea(rect)))
print('Area2: '..tostring(rect.calculateArea2(rect)))
print('Area3: '..tostring(rect.calculateArea3(rect)))

-- `:` passes rect as first arg
print(':Area: '..tostring(rect:calculateArea()))
print(':Area2: '..tostring(rect:calculateArea2()))
print(':Area3: '..tostring(rect:calculateArea3()))

-- you can pass other tables as arguments even though the function is
-- on the `rect` table
print('Other Area:'..tostring(rect.calculateArea({ length = 4, width = 3 }))) -- p
print('Other Area2:'..tostring(rect.calculateArea2({ length = 4, width = 3 })))
print('Other Area3:'..tostring(rect.calculateArea3({ length = 4, width = 3 }

Using the `.` notation, you can see that the function exists as a property on the table like any other table value like `length` and `width`. Since it is a simple function, it's not really tied to the object, it takes a parameter that we called `self` which should be the table to operate on. When calling it with a `.`, we also need to pass the object to operate on because it is just a simple function. Although it exists on our table with length and width specified, there is no real relation.

Now look at `calculateArea2()`. Here we use a `:` when specifying that the function exists on our `rect` table. There are no arguments, but we use `self` inside of the function. By using a `:` in the function declaration, LUA assumes there is a first unspecified argument named `self`. Functionally the two definitions are equivalent, they both take one argument and it's named `self` in both. As you can see by the last two lines, you can pass different tables to each function, even the one defined with a `:`.

And with `calculateArea3` we directly assign the function as a property on the table. All three of these declarations are functionally the same. The functions are simple properties on the `rect` table.

Now look at the function calls where we use a `:`. These don't pass any arguments. That is because when using a `:` when *calling* a function property, the table the function resides on is passed as the first argument. This is the basis for creating methods on objects.