Issue within my custom Class module - Lua - class

I'm currently working on a module that allows JS-Like classes to be implemented easily in Lua
I've added the ability to extend classes but I'm having an issue with extending classes twice, it seems to be some sort of issue within the super constructor function that's causing a recursive call however I can't seem to figure out where the bug is coming from, any help would be appreciated
Module:
local ClassCreator = {}
ClassCreator.extends = {__extends = true}
local function modifyFnEnv(f, env)
local fEnv = getfenv(f)
for i,v in pairs(env) do fEnv[i] = v end
setfenv(f, fEnv)
end
local ClassMt = {
__call = function (self, ...)
local newClass = {}
setmetatable(newClass, {__index = self.prototype})
modifyFnEnv(newClass.constructor, {
self = newClass
})
newClass.constructor(...)
return newClass
end
}
local function makeClass(self, targs)
local Class = {
prototype = {}
}
setmetatable(Class, ClassMt)
local constructor, SuperClass = function() end, Class
for i,v in pairs(targs) do
if i == ClassCreator.extends then
SuperClass = v
setmetatable(Class.prototype, {__index = SuperClass.prototype})
elseif i == "constructor" then
constructor = v
else
Class.prototype[i] = v
end
end
if SuperClass ~= Class then
modifyFnEnv(constructor, {
super = SuperClass.prototype.constructor
})
end
Class.prototype.constructor = constructor
return Class
end
setmetatable(ClassCreator, {
__call = makeClass
})
return ClassCreator
Test Code:
local Class = require("Class")
local Human = Class {
constructor = function(name, age)
self.name = name
self.age = age
end,
describe = function(self)
return string.format(
"My name is %s and I am %d years old",
self.name,
self.age
)
end
}
local Programmer = Class {
[Class.extends] = Human,
constructor = function (name, age, yearsOfExperience)
super(name, age)
self.yearsOfExperience = yearsOfExperience
end,
describe = function(self)
return string.format(
"My name is %s and I am %d years old, I have %d years of experience",
self.name,
self.age,
self.yearsOfExperience
)
end
}
local LuaProgrammer = Class {
[Class.extends] = Programmer,
constructor = function (name, age, yearsOfExperience)
super(name, age, yearsOfExperience)
end,
describe = function(self)
return string.format(
"My name is %s and I am %d years old, I have %d years of experience in Lua",
self.name,
self.age,
self.yearsOfExperience
)
end
}
local John = Human("John", 35)
local JohnProgrammer = Programmer("John", 35, 5)
local JohnLuaProgrammer = LuaProgrammer("John", 35, 5)
print(John:describe())
print(JohnProgrammer:describe())
print(JohnLuaProgrammer:describe())
Expected output:
My name is John and I am 35 years old
My name is John and I am 35 years old, I have 5 years of experience
My name is John and I am 35 years old, I have 5 years of experience in Lua
Current output:
lua: src/test.lua:20: stack overflow
stack traceback:
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
...
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'super'
src/test.lua:20: in function 'constructor'
./src/Class.lua:17: in function 'Programmer'
src/test.lua:51: in main chunk
[C]: ?

The error message tells you that Programmer.constructor recurses infinitely through the call to super. That is, super is Programmer.constructor but should be Human.constructor.
The reason for this is simple: You're messing with function environments (fenv) assuming getfenv to return a different environment for each function. This isn't the case though: By default all functions have the same environment, the global environment _G. You're thus constantly writing to the global environment, overriding previous self and super global variables.
If you fix this, you get a second error since every constructor creates its own table - but only if the metatable is called! Thus when you call super, bypassing the metatable, the function environment still uses the old self instance, overwriting the instance variables.
In general, I'd advise against messing with function environments. It's often bad both for performance and readability. This is another case of messing with function environments gone horribly wrong.
If you really want this as a nice hack to show off Lua's metaprogramming capabilities, this is how I'd rewrite modifyFnEnv:
local function modifyFnEnv(f, env)
setfenv(f, setmetatable(env, {__index = getfenv(f)}))
end
The metatable with __index set allows accessing the previous function environment, but env takes precedence. Note: If this is called multiply times on the same function, it will grow the index chain each time; you'll probably rather want to replace the function environment.
You don't need the __extends key in the Class.extends table; Lua tables are compared by reference, not by value. You can thus move the key checks out of the loop to improve performance.
Here's the fixed Class.lua:
local ClassCreator = {}
ClassCreator.extends = {}
local function modifyFnEnv(f, env)
setfenv(f, setmetatable(env, {__index = getfenv(f)}))
end
local ClassMt = {
__call = function(self, ...)
local newInstance = {}
setmetatable(newInstance, {__index = self.prototype})
getfenv(newInstance.constructor).self = newInstance -- set self
newInstance.constructor(...)
return newInstance
end
}
local function makeClass(self, targs)
local Class = {
prototype = {}
}
setmetatable(Class, ClassMt)
local constructor = targs.constructor or function() end
local constructorEnv = {}
modifyFnEnv(constructor, constructorEnv)
local SuperClass = targs[ClassCreator.extends]
if SuperClass then
setmetatable(Class.prototype, {__index = SuperClass.prototype})
function constructorEnv.super(...)
local super = SuperClass.prototype.constructor
getfenv(super).self = constructorEnv.self
super(...)
end
end
-- Copy prototype
for k, v in pairs(targs) do
Class.prototype[k] = v
end
-- Remove special non-method fields
Class.prototype[ClassCreator.extends] = nil
Class.prototype.constructor = nil
Class.prototype.constructor = constructor
return Class
end
setmetatable(ClassCreator, {
__call = makeClass
})
return ClassCreator
Note that I'm changing the constructor function environment exactly once and only modifying it afterwards, e.g. by setting self or super fields.
test.lua is fine as-is. Output as expected:
$ lua5.1 test.lua
My name is John and I am 35 years old
My name is John and I am 35 years old, I have 5 years of experience
My name is John and I am 35 years old, I have 5 years of experience in Lua
Let me repeat: Don't do this in production code.

Related

Structuring Lua classes

I'm constructing a class in Lua that has a number of groups of related functions within it, but am unsure whether there's a better way to structure it. I currently have to develop for a Lua 5.1 environment but am hopeful that Lua 5.3 will be possible in the near future.
The class will be used in a number of different Lua programs, so I want something I can just drop in as a single chunk of code (the environment I'm programming for means that modules and require aren't and won't be an option).
Ideally I want a black box piece of code (except for the exposed public methods) and not to duplicate code in different classes (to improve maintainability).
What I have at present is (generalised):
function Fclass()
--here I declare a bunch of local functions that can be called by any of the public methods
local function A(parms)
end
--Public methods set 1
--here I declare a bunch of state variables shared by BSelector and GetB
local BSelector = function()
A(parmvalues)
--returns a bunch of iup controls with supporting (complicated) logic
end
local GetB = function()
--returns the values of the iup controls created in Bselector
end
--Public methods set 2
--here I declare a bunch of state variables shared by DSelector and GetD
local DSelector = function()
--returns a bunch of iup controls with supporting (complicated) logic
end
local GetD = function()
A(parmvalues)
--returns the value of the iup controls created in Dselector
end
return{BSelector =BSelector , GetB =GetB, DSelector =DSelector , GetD =GetD}
end
The "B" and "D" groups of methods are totally independent except they both use the local functions "A" etc. (which don't depend on external variables); their state variables ideally should be local to the group.
Is this a sensible structure? Or should I be splitting the "B" and "D" groups into two separate classes and either duplicating the local functions or dropping them in as a separate piece of code? I don't really want to expose the local functions outside the classe(es) because there will inevitably be naming conflicts... Most programs will use all the groups of methods, although there will be some that only use a single group.
Or is there a better way to do this?
I'm invoking them thus:
myB = Fclass()
myD = Fclass()
someresults = myB.Bselector()
otherresults = myD.Dselector()
Updated to add: I'm advised I may not be using the terminology properly and what I'm doing isn't classes. My approach is based on Programming in Lua and was selected because I wanted to keep the state variables for the class? object? private -- not accessible except via the public methods.
In your example, it seems you encapsulate the state of your instances through closures, not table values.
While this has the advantage of stronger encapsulation, as upvalues are invisible from the outside without using the debug library, it also comes with the disadvantage that Lua has to close each method for each instance, wasting some more memory (not a lot though).
Another benefit is that when instance variables are implemented as table fields, they need not be declared before the method, as table indexing is string-based, whereas when implemented as closures, the local varaible needs to be known before the function is defined (this also applies to other methods, which in either implementation work the same way as instance variables).
It's more common to store instance variables as table values inside the object, and passing the object as a first argument to the functions. There's even syntactic sugar for this.
There's lots of ways for doing classes in Lua, with many different tradeoffs (some are better at inheritance, while others perform better, etc.)
Since you don't seem to need any inheritance, you can go with a simple factory function, as you're pretty much doing already.
The way I personally like to build such factory functions is:
local object do
local class = {}
local meta = {__index=class} -- Object metatable
function class:print() -- A method of the class
print("Hello, I am an object and my x is " .. tostring(self.x))
end
function object(self) -- The factory function for the Class
self.x = self.x or 0
return setmetatable(self, meta)
end
end
local o = object {
x = 20
}
o:print()
o.x = 30
o:print()
This has the benefit that, for classes with many methods and many instances, the methods aren't copied into every instance, which saves some memory.
Alternatively, you can do something like this
local object do
local function object_print(self)
print("Hello, I am an object and my x is " .. tostring(self.x))
end
function object(self)
self.x = self.x or 0
self.print = object_print -- Store method directly in the object
return self
end
end
Again, this saves a reference to every method in every instance, wasting some memory. The benefit is that you can now think of classes as traits. When you write
person { name = "henry" }
You can think of it as creating a new person with the name Henry, but you can also think of it as creating an object with the name Henry and adding the person trait to it.
Because of this benefit of combining two concepts of OOP into one implementation and not having any pesky inheritance, it's my favourite way of building objects in Lua in most simple cases.
Update
The trait approach also lends itself to defining several classes/traits together:
local person, human do
-- Some generic method shared by both classes
local function object_get_name(self)
return self.name
end
-- Person uses this as a method, but human uses
-- it as a function through an upvalue. Both work,
-- but have different upsides and downsides.
-- A method of person
local function person_say_hi(self)
print(self:get_name() .. " says hi!")
-- Calling get_name as a method here
end
-- A method of human
local function human_describe(self)
print(object_get_name(self) .. ' is a human!')
-- Calling get_name as an upvalue
end
function person(self)
self.name = self.name or 'A person'
self.say_hi = person_say_hi
self.get_name = object_get_name
-- Needs to be a method because person_say_hi assumes it to be one
return self
end
function human(self)
self.name = self.name or 'A human'
self.describe = human_describe
return self
end
end
-- Create a new person
local henry = person{ name = "Henry" }
henry:say_hi()
-- Create a new human
local steve = human { name = "Steve" }
steve:describe()
-- Change the way henry gets his name
function henry:get_name()
return self.name:upper()
end
-- This only affects henry; all other "person" objects keep their old
henry:say_hi()
-- This only works because say_hi accesses the method
-- Add the person trait to steve
person(steve)
steve:describe() -- Steve is still a human
steve:say_hi() -- Steve is also a person now
Some years ago I built myself a superclass for basic OOP functionality in Lua.
Usage:
Person = LuaObject:extend({
__name = "Person",
name = "",
age = 0,
})
-- constructor
function Person:new(name, age)
Person.__super.new(self)-- calling the super constructor
self.name = name
self.age = age
end
function Person:getName()
return self.name
end
function Person:getAge()
return self.age
end
Feel free to use it:
--[[
LuaObject for basic OOP in Lua
Lua 5.0
]]
local function newIndexFunction(tbl, name, value)
if name == "new" and type(value) == "function" then
local constructor = value
rawset(tbl, name, function(self, ...)
local object = self
if object.__class == nil then
object = {}
object.__class = self
object.__id = string.sub(tostring(object), 8)
self.__index = self
setmetatable(object, self)
end
constructor(object, unpack(arg))-- Lua 5.0
-- constructor(object, ...)-- Lua 5.1+
return object
end)
else
rawset(tbl, name, value)
end
end
local function toStringFunction(tbl)
return tbl:toString()
end
LuaObject = {__name = "LuaObject"}
setmetatable(LuaObject, {__newindex = newIndexFunction, __tostring = toStringFunction})
function LuaObject:extend(class)
class = class or {}
self.__index = self
self.__newindex = newIndexFunction
self.__tostring = toStringFunction
local constructor = nil
if class.new ~= nil then
constructor = class.new
class.new = nil
end
setmetatable(class, self)
if constructor ~= nil then
class.new = constructor
end
class.__super = self
return class
end
function LuaObject:new()
end
function LuaObject:getSuperClass()
return self.__super
end
function LuaObject:getClass()
return self.__class
end
function LuaObject:toString()
return string.format("[%s] %s", self.__class.__name, self.__id)
end
function LuaObject:isInstance(value)
return value ~= nil and type(value) == "table" and getmetatable(value) == self
end
--[[
-- examples
-- basic class
Person = LuaObject:extend({
__name = "Person",
name = "",
age = 0,
})
-- constructor
function Person:new(name, age)
Person.__super.new(self)-- calling the super constructor
self.name = name
self.age = age
end
function Person:getName()
return self.name
end
function Person:getAge()
return self.age
end
-- extending classes
Customer = Person:extend({
__name = "Customer",
id = 0,
})
function Customer:new(id, name, age)
Customer.__super.new(self, name, age)
self.id = id
end
function Customer:getID()
return self.id
end
-- overriding methods
function Customer:getName()
-- calling super methods
local realResult = Customer.__super.getName(self)
if string.len(realResult) <= 5 then
return realResult
else
return string.sub(realResult, 1, 5)
end
end
-- testing
local customer1 = Customer:new(1, "rollback", 19)
local customer2 = Customer:new(2, "Kori", -1)
print(assert(customer1:getName() == "rollb", "Overriding of getName failed"))
print(assert(customer2:getName() == "Kori", "Overriding of getName failed"))
print(assert(customer1:getID() == 1, "Error in getID"))
print(assert(customer1:getAge() == 19, "Error in getAge"))
print(customer1)
]]
You can create 2 up-values for your class functions. the 1st value holds public variables that will be accessed by your class' caller, such as the functions themselves and any caller handled options.
while the 2nd will be for your private values those that are only known and accessible from within the class. You can use this private table to store internal state or other inner workings that will not be exposed to the caller.
function class(first, second)
local public = {first}
local _private = {second}
function _private.A(parms)
--private function not available outside of class.
end
function public:selector() -- public class available to caller
_private.A(parmvalues) -- calls private class
end
function public:get()
return _private[1]
end
return public
end
myB = class('hello', ' world!') --passing in a variable for public, and one for private.
myD = class('hello...', ' world?')
print(myB[1] .. myB:get()) --get a public value, and uses get function to retrieve private value
print(myD[1] .. myD:get())
Additionally if the class functions should never be changed by your user, you can enforce that by changing return public to:
local meta = {
__index = public,
__newindex = function(t, k, v)
error("this table is read-only")
end,
__metatable = false
}
return setmetatable({}, meta) -- this make the public table read only

Avoid repeating a superclass' package name in Matlab

How can I avoid repeating a long tedious package name in matlab classes in the following cases:
When specifying the Superclass, e.g. classdef Class < tediouspkgname.Superclass
When calling the superclass constructor, e.g. obj = obj#tediouspkgname.Superclass(...).
When calling superclass methods, e.g. val = somefunc#tediouspkgname.Superclas(...).
I'm looking for an equivalent of matlabs import statement, which is not usable in these cases unfortunately.
MWE:
Lets have a folder called +tediouspkgname/ in our Matlab path. So Matlab recognizes there's a package called tediouspkgname.
Lets have a Class ExampleClass which is saved in the file +tediouspkgname/ExampleClass.m:
classdef ExampleClass
properties
p
end
methods
function obj = ExampleClass(p)
obj.p = p;
end
function print(obj)
fprintf('p=%s\n',obj.p);
end
end
end
Let there be another Class, derived from ExampleClass, living in the file
+tediouspkgname/DerivedClass.m:
classdef DerivedClass < tediouspkgname.ExampleClass
methods
function obj = DerivedClass(p)
obj = obj#tediouspkgname.ExampleClass(p);
end
function print(obj)
print#tediouspkgname.ExampleClass(obj);
fprintf('--Derived.\n');
end
end
end
I want the following commands to work without errors while mentioning tediouspkgname. as little as possible:
e = tediouspkgname.ExampleClass('Hello');
e.print();
o = tediouspkgname.DerivedClass('World');
o.print();
In particular, this definition of DerivedClass gives me the error ExampleClass is not a valid base class:
classdef DerivedClass < tediouspkgname.ExampleClass
methods
function obj = DerivedClass(p)
obj = obj#tediouspkgname.ExampleClass(p);
end
function print(obj)
import tediouspkgname.ExampleClass
print#ExampleClass(obj);
fprintf('--Derived.\n');
end
end
end
You have two examples at the command line:
e = tediouspkgname.ExampleClass('Hello');
e.print();
o = tediouspkgname.DerivedClass('World');
o.print();
For these cases, you can use import at the command line:
import tediouspkgname.*
e = ExampleClass('Hello');
e.print();
o = DerivedClass('World');
o.print();
and it should work fine.
For the other cases you have (in the class definition line, and when calling a superclass method), you need to use the fully qualified name including the package.
I dislike this aspect of the MATLAB OO system. It's not just that it's tedious to write out the fully qualified name; it means that if you change the name of your package, or move a class from one package to another, you have to manually go through your whole codebase in order to find-and-replace one package name for another.

Is it possible to change method function handlers in MATLAB classdef

I'm trying to use MATLAB OOP. I would like to change the class method handler in the class constructor.
For example, I have a class test where a class method uses one of methods depending on the variablenumber in class properties:
mytest = test(2);
mytest.somemethod();
classdef test < handle
properties
number
end
methods
function obj = test(number)
obj.number = number;
end
function obj = somemethod(obj)
switch obj.number
case 1
obj.somemethod1();
case 2
obj.somemethod2();
case 3
obj.somemethod3();
end
end
function obj = somemethod1(obj)
fprintf('1')
end
function obj = somemethod2(obj)
fprintf('2')
end
function obj = somemethod3(obj)
fprintf('3')
end
end
end
Here the switch operator is used whenever test.somemethod() is called. Can I use switch once only at the time of initialization in the class constructor (ie change the method handler) as follows:
classdef test < handle
properties
number
somemethod %<--
end
methods
% function obj = somemethod(obj,number) % my mistake: I meant the constructor
function obj = test(number)
obj.number = number;
switch number
case 1
obj.somemethod = #(obj) obj.somemethod1(obj);
case 2
obj.somemethod = #(obj) obj.somemethod2(obj);
case 3
obj.somemethod = #(obj) obj.somemethod3(obj);
end
end
function obj = somemethod1(obj)
fprintf('1')
end
function obj = somemethod2(obj)
fprintf('2')
end
function obj = somemethod3(obj)
fprintf('3')
end
end
end
This second implementation of the test class does not work.
For S = test(2); S.somemethod(), there is an error:
Error using test>#(obj)obj.somemethod2(obj) (line ...)
Not enough input arguments.
What's wrong?
First of all, you can't have somemethod as a method and a property. You can get rid of the method and assign a function handle to the property in your constructor.
function self = test(number)
self.number = number;
switch self.number
case 1
self.somemethod = #(obj)somemethod1(obj)
%....
end
end
Also, your current anonymous functions you've passed two copies of the object to the method:
obj.method implicitly passes obj as the first input
obj.method(obj) passes a second copy of obj as the second input
You want to update your object handles to something like the following which will pass a single copy of obj to the method.
obj.somemethod = #obj.somemethod3
Also, when using your class, you'll have to execute somemethod using dot notation since it's a property and not a "real" method
S = test()
S.somemethod()

In Lua, can you get an object name from 'self'?

I'm probably missing something very simple, but when calling a method on an object in Lua, is there a way to get the name of that object from the self variable?
To illustrate what I mean, here is a somewhat contrived example - a simple Stack implementation:
Stack = {}
function Stack:new (...)
instance = {}
instance.elements = {...}
setmetatable(instance, self)
self.__index = self
return instance
end
function Stack:push (...)
for i,v in pairs({...}) do
table.insert(self.elements,v)
end
end
function Stack:pop ()
if #self.elements > 0 then
return table.remove(self.elements)
else
error("Cannot pop, Stack is empty")
end
end
my_stack = Stack:new(2,4)
my_stack:push("dog") -- my_stack.elements = {2,4,"dog"}
print(my_stack:pop()) -- "dog"
print(my_stack:pop()) -- "4"
print(my_stack:pop()) -- "2"
print(my_stack:pop()) -- error: "Cannot pop, Stack is empty"
Is it possible to use the self variable in the Stack:pop error message to output the name of the object it's being called from? I'd like the error message to say "Cannot pop, Stack 'my_stack' is empty".
is there a way to get the name of that object from the self variable?
Objects in Lua don't have names. Only references have names, and variables and table fields are ultimately just references to objects. So if you are asking how to get the name of the reference, clearly you can't, since there could be any number of references with different names, which one would the "self.getName()" return?
You could give each object a unique identifier, say at construction time. Then one of the arguments to new() would be the object name, you would save it as self.name (for example) and then you could access it as required (I would imagine, for log messages or lookup within some associative array). So you would do
my_stack = Stack:new("my_stack", 2,4)
my_stack:push("dog") -- my_stack.elements = {2,4,"dog"}
I am not aware of a way to make new() figure out that the new instance is going to be assigned to a variable called my_stack. In fact I suspect it is not possible not even with the debug module because the assignment will only take place once the new has returned. So there is nothing forcing the name of the object to be the same as the variable, it's entirely up to you. It's not even something you want because, again, you could have multiple references to same stack object:
a = Stack:new("a", 2,4)
b = a -- b and a are the same object in memory
Should the error message mention a or b? I think it is better for you to assign an id to the object and then you always know which object is being talked about in an error message:
a = Stack:new("my_stack_1", 2,4)
b = a
t = { b = { c = a } }
a:push("dog") -- error will mention my_stack_1: clear which object you are referring to
t.b.c:push("dog") -- error will mention my_stack_1: still clear which object you are referring to
If you are worried that from the error message, you can't determine which line calls new(self, "dog"), that's where the debug module could come in handy: with it you can get the line number and file where the call is made, so you could say "object my_stack_1:pop(): no elements left in stack (called from line X of file Y)"
local function get_my_self_name(self)
local i = debug.getinfo(3, 'Sl');
return "'"..(io.open(i.source:match'#(.*)'):read'*a'
:gsub('.-\n','',i.currentline-1)
:match('(.-)[:.]%s*'..debug.getinfo(2,'n').name..'%s*%(')
:match'([%w_]+)%s*$' or '<unnamed>').."' at line #"..i.currentline
end
local Stack = {}
function Stack:new (...)
local instance = {}
instance.elements = {...}
setmetatable(instance, self)
self.__index = self
return instance
end
function Stack:push (...)
for i,v in ipairs({...}) do
table.insert(self.elements,v)
end
end
function Stack:pop ()
if #self.elements > 0 then
return table.remove(self.elements)
else
error("Can't pop, Stack "..get_my_self_name(self).." is empty")
end
end
local my_stack = Stack:new(2,4)
my_stack:push("dog") --my_stack.elements = {2,4,"dog"}
print(my_stack:pop()) --"dog"
print(my_stack:pop()) --"4"
print(my_stack:pop()) --"2"
print(my_stack:pop()) --error: Can't pop, Stack 'my_stack' at line #35 is empty

How to add event listener for an object that i assigned a value from another class in Lua?

I am trying to write a touch event for the object that i assigned the value of another class' function value into. However, it gives me this error: attempt to call 'addEventListener' nil value.
Here is my fish.lua code:
function class()
local cls = {}
cls.__index = cls
return setmetatable(cls, {__call = function (c, ...)
instance = setmetatable({}, cls)
if cls.__init then
cls.__init(instance, ...)
end
return instance
end})
end
Color= class()
function Color:__init(image)
self.image=display.newImage(image,30,30)
end
originalImage="fish.small.red.png"
differentImage="fish.small.blue.png"
And here is my main.lua code:
require "fish"
local fishImage=Color(originalImage)
function listen(event)
if(phase.event=="began") then
fishImage=Color(differentImage)
end
end
fishImage: addEventListener("touch", listen)
fishImage is an instance of a class you created (Color) which doesn't have a method named addEventListener, at least not in the code you've shown. Perhaps you meant:
fishImage.image:addEventListener('touch', listen)
Which is adding an event listener to the corona image object your Color class encapsulates.
You have a lots of bugs. But use this as an example:
fish.lua
local fish = {}
fish.color = function(image)
local image = display.newImage(image,30,30)
return image
end
return fish
main.lua
display.setStatusBar(display.HiddenStatusBar)
local fish = require("fish")
local fishImage = fish.color("Icon.png")
local function listen(event)
if(event.phase=="began") then
fishImage=fish.color("Icon-60.png")
end
end
fishImage:addEventListener("touch", listen)