EDIT I have found a much easier way to do this in lua but the problem is method inheritance
basically the syntax would go like this
Object
object = {}
object.base = ?
object.value = 0
function object:create(x, y)
local copy
--copy table
if type(self) == "table" then
copy = {} for k, v in pairs(self) do copy[k] = v:create() end
else
copy = self
end
--set base
copy.base = self
--set copy vars
copy.x = x
copy.y = y
return copy
end
function object:update()
self.value = self.value + 1
end
Player
player = object:create()
player.value = 1
function player:create(x, y, size)
base:create(x, y) --inherit base event
end
--automaticly inherits update event since it is not redeclared
I'm not sure how to go about doing this though
Inheritance in Lua is basically implemented using metatables. In code:
function object:new (o)
o = o or {}
-- Put the rest of your create function code here
setmetatable(o, self)
self.__index = self
return o
end
function object:update()
self.value = self.value + 1
end
Now create an empty Player class that will be a subclass of your base Object class and will inherit all its behavior from it.
Player = Object:new()
Player is now an instance of Object. Instantiate a new Player object, p in order to inherit the new method from Object.
p = Player:new{x=1, y=2, size=3}
This time, however, when new executes, the self parameter will refer to player. Therefore, the metatable of p will be Player, whose value at index __index is also Player. So, p inherits from Player, which inherits from Object.
Now when you'll code:
p:create{x=10, y=20, size=100}
lua won't find a create field in p, so it will look into Player class; it won't find a create field there, too, so it will look into Object and there it will finds the original implementation of create. The same thing will happen with the update function.
Of course Player class can redefine any method inherited from its superclass, Object. So for example you can redefine -if you want- the create function:
function Player:create()
--New create code for Player
end
Now when you'll call p:create{x=10, y=20, size=190}, Lua will not access the Object class, because it finds the new create function in Player first.
You are making a reference to base directly, whereas, it is actually an attribute of your player object:
function player:create(x, y, size)
self.base:create(x, y)
end
Related
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
I've made a mistake and recorded a bunch of important data using a class definition that I can't find anymore. The methods are not important, I just want the data; a struct conversion would be fine.
Is there any way I can recover this?
Googling it did not help.
The solution is to create a new class that overloads the loadobj method. See here for more information regarding the load process for classes.
I replicated your problem by creating a class:
classdef myclass
properties
Prop1
Prop2
Prop3
end
methods
function obj = myclass(a,b,c)
obj.Prop1 = a;
obj.Prop2 = b;
obj.Prop3 = c;
end
end
end
Then I created an object of this class and saving it to a file "x.mat":
x = myclass('a',56,[1,2,3]);
save x
Next, I deleted the myclass file and did clear classes. This put me in your situation.
I then created a new myclass class that overloads the loadobj method:
classdef myclass
properties
data
end
methods (Static)
function obj = loadobj(s)
obj = myclass;
obj.data = s;
end
end
end
Note how it doesn't know any of the original properties. This does not matter. If any of the original properties is missing when loading an object from a MAT-file, loadobj will be called with s being a struct containing all the properties of the original object.
With this new class definition, load x created an object x of class myclass, where x.data was a struct containing the properties of the object saved in "x.mat".
Given a table, is there a way to check if it is an instance object of any class?
Assume all class definition looks like:
Class = {}
Class.__index = Class
function Class.new()
return setmetatable({}, Class) -- returns an instance
end
I use just getmetatable function
if getmetatable(thing) == Class then
But if you use some type of inheritence then you can try this one
local A = {} A.__index = A
function A:new() return setmetatable({}, A) end
function A:foo() print('foo') end
local B = setmetatable({}, A) B.__index = B
function B:new() return setmetatable({}, B) end
function B:boo() print("boo") end
local function is_instance(o, class)
while o do
o = getmetatable(o)
if class == o then return true end
end
return false
end
local a = A:new()
local b = B:new()
a:foo()
b:foo()
b:boo()
print(is_instance(a, A))
print(is_instance(a, B))
print(is_instance(b, B))
print(is_instance(b, A))
In theory you could read table's metatable with getmetatable(), and compare received table agains list of classes known to you.
But it means metatable shouldn't be protected (__metatable field is not set to something different, getmetatable() is not removed within sandbox, etc), and you should know all available classes.
If there some metatable set on a table, it doesn't mean that table is a part of class hierarchy, or class at all. It just might use metatables to solve its own tasks.
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)
So I come from the traditional game development that uses OOP principles and from what I've seen you can mimic this using LUA once you know what you are doing. In some of the code postings I found out how you can use the director class and create files that have a new() function etc.
What I'm looking for is a way to manage my weapons. I have a player and an opponent and I would prefer to have one weapon class, say weaponCanon. What I have done is:
-- private vars here
local power
local canonSprite
local whatever
local someFunction = function()
...
end
-- Private stuff here
local weaponCanon = {}
weaponCanon.fire = function(atX, atY)
...
end
weaponCanon.reset = function()
...
end
return weaponCanon
Then in my level code I simply do:
local weaponCanon = require("weaponCanon")
weaponCanon.fire(100, 100)
This works great and allows me to use a "private" and "public" mentality when coding up my weapons. The problem is that if I want the player and opponent to have a canon:
local playerWeapon = require("weaponCanon")
local opponentWeapon = require("weaponCanon")
This simply returns the same object instead of a new instance to that object. So I only get one weaponCanon at the opponentWeapon location. This is obviously now what I want/need.
Our game has many weapons in it and it would be nice to only have one version of each file with a setting telling us if its the opponents weapon or players weapon. The alternative is to copy each file and create a weaponPlayerCanon and a weaponOpponentCanon but I cringe at the thought of modifications to one file and having to change 2+ files every time.
How can I make it return an instance and what is the structure of the LUA file to do so?
Thanks or any and all help
-d
If later on you start needing inheritance (i.e. LaserCannon is a subclass of Weapon) you will probably need to use metatables more profoundly.
There are lots of libraries that will allow you to do "oop on top of Lua". You can see a very good list here:
http://lua-users.org/wiki/ObjectOrientedProgramming
I'm the author of middleclass. With my lib, you would have to do something like this:
local Weapon = class('Weapon')
function Weapon:initialize(a,b,c)
self.x,self.y,self.z = a,b,c
end
function Weapon:fire(x,y)
...
end
LaserCannon would be easy to implement - you just pass a second parameter to class:
local LaserCannon = class('LaserCannon', Weapon)
function LaserCannon:initialize(a,b,c,d)
self.w = d
Weapon.initialize(self, a,b,c) -- superclass' constructor
end
function LaserCannon:foo()
...
end
You could use it like this:
require 'middleclass' -- so you can use "class"
LaserCannon = require 'laser_cannon'
local playerWeapon = LaserCannon:new() -- a laser
local opponentWeapon = Weapon:new() -- a regular generic weapon
opponentWeapon:fire(100,200) -- typical use
playerWeapon:fire(100, 200) -- LaserCannon inherits fire from Weapon
playerWeapon:foo() -- LaserCannon-exclusive
This is with middleclass, which is the one I prefer, since I made it. Other libraries on the page I mentioned before offer similar features.
I guess you are trying to model a class with your source file. This means you should also have a function to create a new instance of that class unless you want them to share all their state.
Something along the lines of (untested):
local WeaponCannon = {}
WeaponCannon.__index = WeaponCannon
function WeaponCannon:new()
return setmetatable({}, self)
end
function WeaponCannon:fire(x, y)
-- Do something via the self reference and arguments (x, y)
end
return WeaponCannon
And in your calling code (also untested):
require('WeaponCannon')
local playerWeapon = WeaponCannon:new()
local opponentWeapon = WeaponCannon:new()
Although you create a new table for the weapon object, you don't create new variables. Any variables declared at the top of your module like that are essentially static variables (ie. variables shared by all instances of a class.) To create variables that are unique to that object you need to create them in the table, something like:
weaponCannon = {}
weaponCannon.power = 10
And anyway you only create an object once, you need a "constructor" function that creates the tables:
function new()
local weaponCannon = {}
weaponCannon.power = 10
end
Incidentally, two other things that aren't directly related to your answer but can be very useful modifications to your code. First off, using a colon instead of a period to call functions in a method will allow you to use the "self" keyword inside the method, something like:
function weaponCannon:fire()
--this is only a test
print(self.power)
end
then
local playerWeapon = require("weaponCanon")
playerWeapon:fire()
Second, you can actually use display objects as tables, rather than having to create an empty table and then sticking the display object into that empty table:
weaponCannon = display.newImage("cannon.png")
weaponCannon.power = 10
Note that you can't set the meta-table if you do this however. I find this approach looks more logical and prefer not to use meta-tables myself, but that's your call.
There are no objects here- you just have a bunch of global data. You really need to be making instances.
function NewWeapon(arg)
return {
fire = function(self, atX, atY)
print(self.var)
end,
var = arg,
}
end
NewWeapon(3):fire(1, 2)
NewWeapon(7):fire(3, 5)
I like ponzao's answer. Would however change it to:
local WeaponCannon = {}
function WeaponCannon:new()
local instance = {}
setmetatable(instance, {__index = WeaponCannon})
-- setup your new instance here
return instance
end
function WeaponCannon:fire(x, y)
-- Do something via the self reference and arguments (x, y)
end
return WeaponCannon
And in your calling code:
local WeaponCanon = require('WeaponCannon')
local playerWeapon = WeaponCannon:new()
local opponentWeapon = WeaponCannon:new()
What I've changed:
Created a local instance variable to allow for setup before returning it
More compact way of setting the metatable
Use a variable for the class when calling the code