Lua class methods - class

I'm trying to create Ball class and have some methods in the class but I can't find the right syntax
Tried reading this: https://www.lua.org/pil/16.html
MovingObj = {}
function MovingObj:new(o)
return o
end
ball = MovingObj:new {}
MovingObj.test = function (self)
print ("Test!")
end
ball:test()
Error message I get: attempt to call method 'test' (a nil value)

o is just a empty table, you dont apply a metatable to it which would allow access to the functions of MovingObj
You can correct this by applying a metatable during your new function:
MovingObj = {}
function MovingObj.new(o)
o = o or {}
local meta = {
__index = MovingObj -- when o does not have a given index check MovingObj for that index.
}
return setmetatable(o, meta) -- return o with the new metatable applied.
end
ball = MovingObj.new({type = "ball"})
function MovingObj:test()
print ("Test! I'm a " .. self.type)
end
ball:test()
It is also not necessary to use the : syntax for this new function, we are not using the self variable.

Related

Lua: how do I return the module itself when requiring a module?

I want to create a module something like this
myclass.lua
local myclass = {
print = function()
` print(myclass.name)
end,
setname = function(name)
myclass.name = name
end
}
-- Constructor
local function new(name)
local o = {name = ""}
setmetatable(o, myclass)
return o
end
return _this_module__ <<== How can I do this?:
In order to use this module like this:
myclasscode = require("myclass")
local object1 = myclasscode.new("hello")
local object2 = myclasscode.new("goodbye")
You need to define it on your own. The "module" here, or rather the thing that require returns is whatever is returned by the required file. For instance:
one.lua:
return 1
and then:
print(require("one")) --> 1
In the usual case you want to provide a set of functions to the user. Using tables is the most straight-forward choice to do it:
myclass.lua:
local function new(name)
-- constructor code here
end
return {
new=new,
-- anything else that the module should provide
}
require will return the table with the 'new' member that holds the constructor function. User then can use it like this:
local myclass = require("myclass")
local instance = myclass.new("hey")
Because it's just a regular value you can do whatever you want with it. You can get quite close to what you wanted with:
local _this_module_ = {}
function _this_module_.new(name)
-- constructor code here
end
return _this_module_

I see nothing in my object "PrincipalProduit__c"

I want to update the information contained in my "var" variable in my "PrincipalProduit__c" object,
using this function
public void DMLOperation () {
List <PrincipalProduit__c> letter = getValo ();
List <PrincipalProduit__c> updateList = new List <PrincipalProduit__c> ();
system.debug (letter);
for (PrincipalProduit__c opps: letter) {
updateListe.add (opps);
system.debug (opps);
}
update (sObject []) updateList;
}
But when I make a debug of my valriable "letter" I do not see any value.
what I would like to do is to be able to update the data in my object "principalProduct__c" because in this table the data are incomplete
Here is the code that returns the data that I want to update in my "PrincipalProduit__c" object
public List<PrincipalProduit__c> getValo(){
List<PrincipalProduit__c> searchList = new List<PrincipalProduit__c>();
List<PrincipalProduit__c> var = new List<PrincipalProduit__c>();
for (integer l = 0; l < data.size(); l++) {
searchList=[SELECT id From PrincipalProduit__c where Email__c=:data[l][0]];
system.debug(searchList);
for (PrincipalProduit__c principalProd :searchList) {
principalProd.CodeAlliance__c = data[l][1];
var.add(principalProd);
}
}
system.debug(var);
return var;
}
First of all,
In
List <PrincipalProduit__c> updateList = new List <PrincipalProduit__c> ();
the variable is updateList, but you are using updateListe in the inner part.
updateListe.add (opps);

Lua classes: how do I access the object when running one of it's methods?

I am using this for classes:
http://pastebin.com/DHVXsH37
Here is my code:
require 'class'
-- General node class and functions
Node = class(function(node, ID, x, y)
node.nodetype = 'neutral';
node.id = ID;
node.x = x;
node.y = y;
node.fname = 'exnode.png'
end)
function Node:display()
print( self.fname )
local img = display.newImage( self.fname, self.x, self.y );
img:addEventListener( "tap", self.onTap )
end
When running the display function of an initialized instance. I get an error saying that self is not defined. How do I get the properties of the object?
As Etan said in the comment, make sure you call your method as object:method() and not as object.method() as in the first case self value is set to object and in the second case it's not set to anything (so has nil value). object:method(...) notation is a syntax sugar for object.method(object, ...).

How to stop Coffeescript from escaping keywords?

I am trying to write a indexeddb function "delete". It should read like this in JS:
var transaction = db.transaction('objectStore','readwrite');
var objectStore = transaction.objectStore('objectStore');
objectStore.delete(id);
However, when I write it in CS:
transaction = db.transaction 'objectStore','readWrite'
objectStore = transaction.objectStore 'objectStore'
objectStore.delete(id)
Of course it outputs:
...
objectStore["delete"](id);
I didn't write a method for IDBTransaction called "delete", but I have to use it. How can I keep CS from escaping the "delete" method and turning it into a "delete" key in an object?
Use backticks to pass through bare Javascript:
`objectStore.delete(id)`
will be compiled through verbatim. Try it here at my favorite site for interpreting between CS and JS: http://js2coffee.org/#coffee2js
transaction = db.transaction 'objectStore','readWrite'
objectStore = transaction.objectStore 'objectStore'
`objectStore.delete(id)`
becomes
var objectStore, transaction;
transaction = db.transaction('objectStore', 'readWrite');
objectStore = transaction.objectStore('objectStore');
objectStore.delete(id);
Why do you care that the JavaScript version is objectStore["delete"](id)? That's the same as objectStore.delete(id).
For example, if you say this in CoffeeScript:
class B
m: (x) -> console.log("B.m(#{x})")
class C extends B
c = new C
c.m('a')
c['m']('b')
The last two lines come out as this JavaScript:
c.m('a');
c['m']('b');
but they both call the same method.
Demo: http://jsfiddle.net/ambiguous/XvNzB/
Similarly, if you say this in JavaScript:
var o = {
m: function(x) { console.log('m', x) }
};
o.m('a');
o['m']('b');
The last two lines call the same method.
Demo: http://jsfiddle.net/ambiguous/Y3eUW/

How to create a class, subclass and properties in Lua?

I'm having a hard time grokking classes in Lua. Fruitless googling led me to ideas about meta-tables, and implied that third-party libraries are necessary to simulate/write classes.
Here's a sample (just because I've noticed I get better answers when I provide sample code):
public class ElectronicDevice
{
protected bool _isOn;
public bool IsOn { get { return _isOn; } set { _isOn = value; } }
public void Reboot(){_isOn = false; ResetHardware();_isOn = true; }
}
public class Router : ElectronicDevice
{
}
public class Modem :ElectronicDevice
{
public void WarDialNeighborhood(string areaCode)
{
ElectronicDevice cisco = new Router();
cisco.Reboot();
Reboot();
if (_isOn)
StartDialing(areaCode);
}
}
Here is my first attempt to translate the above using the technique suggested by Javier.
I took the advice of RBerteig. However, invocations on derived classes still yield: "attempt to call method 'methodName' (a nil value)"
--Everything is a table
ElectronicDevice = {};
--Magic happens
mt = {__index=ElectronicDevice};
--This must be a constructor
function ElectronicDeviceFactory ()
-- Seems that the metatable holds the fields
return setmetatable ({isOn=true}, mt)
end
-- Simulate properties with get/set functions
function ElectronicDevice:getIsOn() return self.isOn end
function ElectronicDevice:setIsOn(value) self.isOn = value end
function ElectronicDevice:Reboot() self.isOn = false;
self:ResetHardware(); self.isOn = true; end
function ElectronicDevice:ResetHardware() print('resetting hardware...') end
Router = {};
mt_for_router = {__index=Router}
--Router inherits from ElectronicDevice
Router = setmetatable({},{__index=ElectronicDevice});
--Constructor for subclass, not sure if metatable is supposed to be different
function RouterFactory ()
return setmetatable ({},mt_for_router)
end
Modem ={};
mt_for_modem = {__index=Modem}
--Modem inherits from ElectronicDevice
Modem = setmetatable({},{__index=ElectronicDevice});
--Constructor for subclass, not sure if metatable is supposed to be different
function ModemFactory ()
return setmetatable ({},mt_for_modem)
end
function Modem:WarDialNeighborhood(areaCode)
cisco = RouterFactory();
--polymorphism
cisco.Reboot(); --Call reboot on a router
self.Reboot(); --Call reboot on a modem
if (self.isOn) then self:StartDialing(areaCode) end;
end
function Modem:StartDialing(areaCode)
print('now dialing all numbers in ' .. areaCode);
end
testDevice = ElectronicDeviceFactory();
print("The device is on? " .. (testDevice:getIsOn() and "yes" or "no") );
testDevice:Reboot(); --Ok
testRouter = RouterFactory();
testRouter:ResetHardware(); -- nil value
testModem = ModemFactory();
testModem:StartDialing('123'); -- nil value
Here's an example literal transcription of your code, with a helpful Class library that could be moved to another file.
This is by no means a canonical implementation of Class; feel free to define your object model however you like.
Class = {}
function Class:new(super)
local class, metatable, properties = {}, {}, {}
class.metatable = metatable
class.properties = properties
function metatable:__index(key)
local prop = properties[key]
if prop then
return prop.get(self)
elseif class[key] ~= nil then
return class[key]
elseif super then
return super.metatable.__index(self, key)
else
return nil
end
end
function metatable:__newindex(key, value)
local prop = properties[key]
if prop then
return prop.set(self, value)
elseif super then
return super.metatable.__newindex(self, key, value)
else
rawset(self, key, value)
end
end
function class:new(...)
local obj = setmetatable({}, self.metatable)
if obj.__new then
obj:__new(...)
end
return obj
end
return class
end
ElectronicDevice = Class:new()
function ElectronicDevice:__new()
self.isOn = false
end
ElectronicDevice.properties.isOn = {}
function ElectronicDevice.properties.isOn:get()
return self._isOn
end
function ElectronicDevice.properties.isOn:set(value)
self._isOn = value
end
function ElectronicDevice:Reboot()
self._isOn = false
self:ResetHardware()
self._isOn = true
end
Router = Class:new(ElectronicDevice)
Modem = Class:new(ElectronicDevice)
function Modem:WarDialNeighborhood(areaCode)
local cisco = Router:new()
cisco:Reboot()
self:Reboot()
if self._isOn then
self:StartDialing(areaCode)
end
end
If you were to stick to get/set methods for properties, you wouldn't need __index and __newindex functions, and could just have an __index table. In that case, the easiest way to simulate inheritance is something like this:
BaseClass = {}
BaseClass.index = {}
BaseClass.metatable = {__index = BaseClass.index}
DerivedClass = {}
DerivedClass.index = setmetatable({}, {__index = BaseClass.index})
DerivedClass.metatable = {__index = DerivedClass.index}
In other words, the derived class's __index table "inherits" the base class's __index table. This works because Lua, when delegating to an __index table, effectively repeats the lookup on it, so the __index table's metamethods are invoked.
Also, be wary about calling obj.Method(...) vs obj:Method(...). obj:Method(...) is syntactic sugar for obj.Method(obj, ...), and mixing up the two calls can produce unusual errors.
There are a number of ways you can do it but this is how I do (updated with a shot at inheritance):
function newRGB(r, g, b)
local rgb={
red = r;
green = g;
blue = b;
setRed = function(self, r)
self.red = r;
end;
setGreen = function(self, g)
self.green= g;
end;
setBlue = function(self, b)
self.blue= b;
end;
show = function(self)
print("red=",self.red," blue=",self.blue," green=",self.green);
end;
}
return rgb;
end
purple = newRGB(128, 0, 128);
purple:show();
purple:setRed(180);
purple:show();
---// Does this count as inheritance?
function newNamedRGB(name, r, g, b)
local nrgb = newRGB(r, g, b);
nrgb.__index = nrgb; ---// who is self?
nrgb.setName = function(self, n)
self.name = n;
end;
nrgb.show = function(self)
print(name,": red=",self.red," blue=",self.blue," green=",self.green);
end;
return nrgb;
end
orange = newNamedRGB("orange", 180, 180, 0);
orange:show();
orange:setGreen(128);
orange:show();
I don't implement private, protected, etc. although it is possible.
If you don't want to reinvent the wheel, there is a nice Lua library implementing several object models. It's called LOOP.
The way I liked to do it was by implementing a clone() function.
Note that this is for Lua 5.0. I think 5.1 has more built-in object oriented constructions.
clone = function(object, ...)
local ret = {}
-- clone base class
if type(object)=="table" then
for k,v in pairs(object) do
if type(v) == "table" then
v = clone(v)
end
-- don't clone functions, just inherit them
if type(v) ~= "function" then
-- mix in other objects.
ret[k] = v
end
end
end
-- set metatable to object
setmetatable(ret, { __index = object })
-- mix in tables
for _,class in ipairs(arg) do
for k,v in pairs(class) do
if type(v) == "table" then
v = clone(v)
end
-- mix in v.
ret[k] = v
end
end
return ret
end
You then define a class as a table:
Thing = {
a = 1,
b = 2,
foo = function(self, x)
print("total = ", self.a + self.b + x)
end
}
To instantiate it or to derive from it, you use clone() and you can override things by passing them in another table (or tables) as mix-ins
myThing = clone(Thing, { a = 5, b = 10 })
To call, you use the syntax :
myThing:foo(100);
That will print:
total = 115
To derive a sub-class, you basically define another prototype object:
BigThing = clone(Thing, {
-- and override stuff.
foo = function(self, x)
print("hello");
end
}
This method is REALLY simple, possibly too simple, but it worked well for my project.
It's really easy to do class-like OOP in Lua; just put all the 'methods' in the __index field of a metatable:
local myClassMethods = {}
local my_mt = {__index=myClassMethods}
function myClassMethods:func1 (x, y)
-- Do anything
self.x = x + y
self.y = y - x
end
............
function myClass ()
return setmetatable ({x=0,y=0}, my_mt)
Personally, I've never needed inheritance, so the above is enough for me. If it's not enough, you can set a metatable for the methods table:
local mySubClassMethods = setmetatable ({}, {__index=myClassMethods})
local my_mt = {__index=mySubClassMethods}
function mySubClassMethods:func2 (....)
-- Whatever
end
function mySubClass ()
return setmetatable ({....}, my_mt)
update:
There's an error in your updated code:
Router = {};
mt_for_router = {__index=Router}
--Router inherits from ElectronicDevice
Router = setmetatable({},{__index=ElectronicDevice});
Note that you initialize Router, and build mt_for_router from this; but then you reassign Router to a new table, while mt_for_router still points to the original Router.
Replace the Router={} with the Router = setmetatable({},{__index=ElectronicDevice}) (before the mt_for_router initialization).
Your updated code is wordy, but should work. Except, you have a typo that is breaking one of the metatables:
--Modem inherits from ElectronicDevice
Modem = setmetatable({},{__index,ElectronicDevice});
should read
--Modem inherits from ElectronicDevice
Modem = setmetatable({},{__index=ElectronicDevice});
The existing fragment made the Modem metatable be an array where the first element was almost certainly nil (the usual value of _G.__index unless you are using strict.lua or something similar) and the second element is ElectronicDevice.
The Lua Wiki description will make sense after you've grokked metatables a bit more. One thing that helps is to build a little infrastructure to make the usual patterns easier to get right.
I'd also recommend reading the chapter on OOP in PiL. You will want to re-read the chapters on tables and metatables too. Also, I've linked to the online copy of the 1st edition, but owning a copy of the 2nd is highly recommended. There is also a couple of articles in the Lua Gems book that relate. It, too, is recommended.
Another simple approach for subclass
local super = require("your base class")
local newclass = setmetatable( {}, {__index = super } )
local newclass_mt = { __index = newclass }
function newclass.new(...) -- constructor
local self = super.new(...)
return setmetatable( self, newclass_mt )
end
You still can use the functions from superclass even if overwritten
function newclass:dostuff(...)
super.dostuff(self,...)
-- more code here --
end
don't forget to use ONE dot when pass the self to the superclass function