2
votes

How would one extend a library in Lua such that:

  • don't touch the file you're extending
  • want to add another method to the class
  • want to have your own custom name for the library class (i.e. not just "M")
  • KEY: have the ability for the function you add to have access to the library's local functions. So it's as if you put the function directly into the 3rd party Library, but in fact it's not, you've separated it out into another file (your own) to avoid issues when the library file is updated
  • for your info: using Corona SDK in this case

Example below: Here there is an error: "Attempt to call global 'getANumber' (a nil value)". Any better ways to do it welcomed too in terms of approach.

main.lua

local myLibrary = require("library")
local myLibraryExtension = require("myLibraryExtension")
myLibraryExtension:extend(myLibrary)

myLibrary:doX()
myLibrary:doY()   -- <=== ERROR HERE

library.lua

local M = {}

local function getANumber()
    return 55
end

function M:doX()
    print("X", getANumber())
end

return M

myLibraryExtension.lua

local M = {}

local function doY()
    print("X", getANumber())
end

function M:extend(sourceClass)
    sourceClass.doY = doY
end

return M
1
Usually when you use local variables you want them to be private and you write your code assuming that noone else can tamper with your locals. Additionally, the only way to access them from outside is with the debug library. Is there a reason why you can't just make these functions public or put them in a table that you pass to the extensions (perhaps using setfenv or _ENV to get better syntax)? - hugomg
@hugomg it's just that it's a 3rd party library, so I wanted not to touch it at all to avoid any issues if there were updates to it - does this make sense? - Greg
Since you want to fiddle with the internals of the library you can't trust that future versions of the library will be compatible with your extensions. They could get rid of getANumber or subtly change how it behaves. At this point you might as well just fork the library and edit the original file. - hugomg

1 Answers

2
votes

You can not call the getANumber function from your myLibraryExtension.lua file. The local function exists only in the library.lua scope and can't be used outside for the reason as explained in comments by hugomg. If you want access to private (read local) function, you can modify scripts like this:

library.lua

Add the following statement before return M

M.getANumber = getANumber

myLibraryExtension.lua

Modify the function doY a little:

local function doY(this)
    print("X", this.getANumber())
end

What happens is, when you execute the statement

myLibrary:doY()

lua executes it as follows:

myLibrary.doY( myLibrary ) -- yes, myLibrary is passed as an argument too

You can use the passed reference to the library to your benefit by extending the doY function to accept an argument as well (this in my case).

This object can then have the access to the desired local function.