Class structure in Lua/Corona - oop

So I'm working on a game in Lua and I'm trying to use metatables and classing but I think I'm importing my PHP knowledge and doing things slightly sideways.
-- Basic Monster
Monster = {}
function Monster:new(newX, newY)
local newMonster = {x = newX, y = newY}
setmetatable(newMonster, {__index = Monster})
return newMonster
end
function Monster:moveTo(newX, newY)
self.x = newX
self.y = newY
end
function Monster:takeDamage()
self.hitPoints = self.hitPoints - playerWeapon.damage
if self.hitPoints <= 0 then
self.die()
end
end
function Monster:tap()
self.takeDamage()
end
function Monster:die()
self.removeSelf()
end
--Groblin
Groblin = {}
setmetatable(Groblin, {__index = Monster})
function Groblin:new(newX, newY)
local groblin = display.newImage('assets/images/goblin.png');
groblin.hitPoints = 4
physics.addBody(groblin, 'static')
gameGroup.insert(groblin)
return groblin
end
I'm basically looking to be able to spawn several different types of monsters, and retain some base class functionality for them, but I'm uncertain in the above example how I tie in the base class to the Groblin class I made as I feel like I blew out that subclass altogether by what I'm doing inside of Groblin:new.

If you want classes that you can subclass, try using middleclass. It's not very trivial to do subclasses in standard lua and middleclass has taken care of the boilerplate.
Also, make use of local -- use it anywhere it can be used.

A simple way to do this with your example would be:
function Groblin:new(newX, newY)
local groblin = Monster:new( newX, newY )
setmetatable(groblin, {__index = Groblin})
groblin.image = display.newImage('assets/images/goblin.png');
-- ...
return groblin
end
Use the base class ":new()" method to construct the object and then add the unique fields for the subclass. This insures the base class is properly constructed. Re-setting the metatable to "Groblin" in the subclass constructor insures that any methods defined for the Groblin subclass are called if available, and where the Groblin table does not re-define a method the superclass method will be called.
It probably is better to use a library that provides a consistent approach for object creation and subclassing, but hopefully that gives you a better idea of how to do things manually.

Check out http://www.lua.org/pil/16.2.html for inheritance.
Pay a little attention on the explanation of how the use of self in Account:new works out best while SpecialAccount extends Account.
I generally follow a little different approach than the mentioned in above link. In the above approach -
SpecialAccount = Account:new()
s = SpecialAccount:new{limit=1000.00}
You are calling Account:new() twice, and more problem arises when Acoount:new() does some validaiton on constructor parameters and throws exceptions. For ex: ensuring that the limit passed in non-nil.
So I follow this
SpecialAccount = setmetatable({__index = Account})
Does the trick of allowing superclass constructor to be used in subclasses.
PS: I prefer to treat new function as a constructor. It essentially does the same job.

Related

OCaml Encapsulation

I'm facing a problem and studying the OCaml documentation did not enable me to find a satisfying solution yet.
The following snippet illustrates my problem:
class A = object (self)
(* this should not be overwrittable in subclass B, but callable
on objects of type B!
*)
method dangerous_one input =
(do dangerous stuff...)
let safe_output = safe_dangerous_one input in
(... more dangerous things done with safe_output ...)
(* This is safe, should be overwrittable and callable in subclass *)
method safe_dangerous_one input = (...)
end
class B = object(self) inherit A as super
method! safe_dangerous_one input = (* subclass behaviour ... *)
end
To sum up the snippet: class A is base class to subclass B.
It has a dangerous method that is complex and has some dark corners I don't want client code to have to deal with.
In fact, I want to prohibit subclasses from overwriting method "dangerous_one".
Instead, they should overwrite the function "safe_dangerous_one".
Furthermore, it should be possible to CALL "b#dangerous_one" where "b : B" which uses the (new) definition of the "safe_dangerous"-parts as specified in class B.
My dilemma appears to be: if I simply make method "dangerous_one" private, nothing keeps the client code in class B from overwriting it, potentially even making it public.
If I hide its implementation from the signature, it can not be overwritten anymore, but I cannot call "b#dangerous_one" anymore - the code becomes inaccessible to calls also.
Is there any way to achieve what I aim to do?
Best,
Nablezen
If I hide its implementation from the signature, it can not be overwritten anymore, but I cannot call "b#dangerous_one" anymore - the code becomes inaccessible to calls also.
You can, you just need to make it private, you can't hide public methods:
class type safe = object
method safe_dangerous_one : in_channel -> int
end
class a : safe = object (self)
method private dangerous_one input = input_binary_int input
method safe_dangerous_one input =
max 255 (self#dangerous_one input)
end
class b parameters = object(self)
inherit a parameters as super
method! safe_dangerous_one input =
super#safe_dangerous_one input + 1
end
If you want unsafe method to be accessible, but not overridable, then just re-publish it at another name (kind of NVI):
class type safe = object
method unsafe_dangerous_one : in_channel -> int
method safe_dangerous_one : in_channel -> int
end
class a : safe = object (self)
method private dangerous_one input = input_binary_int input
method unsafe_dangerous_one input = self#dangerous_one input
method safe_dangerous_one input =
max 255 (self#dangerous_one input)
end
class b = object(self)
inherit a as super
method! safe_dangerous_one input =
super#safe_dangerous_one input + 1
end
And a piece of free advice. In other languages, classes and methods are used as a tool for structuring programs, because they have no better tools. In OCaml you have first class functions, records, structures, etc. So it is better to use a proper tool for at each situation. When you design a class, you should understand, that the method by its original definition (not spoiled by C++/Java/Python/etc) is something overridable. A method is an operation that has an implementation that varies across some genera. So, if you define something as a method, and then trying hard to prevent people from overriding it, then chances are high that you're doing something wrong. If you don't want it to be overridable, then just don't define it as a method at all. In your case you should put dangerous_one operation into a let-bound function. You can bound it in the context of the class, so that you will have an access to all parameters, or you can bind it on a toplevel, the choice is yours:
class a parameters =
let dangerous_one input = input_binary_int input in
object (self)
method safe_dangerous_one input =
max 255 (dangerous_one input)
end
class b = object(self)
inherit a as super
method! safe_dangerous_one input =
super#safe_dangerous_one input + 1
end
Also, a very good source of documentation about OCaml class system is Jason Hickey's Introduction to Objective Caml. It is slightly outdated, but is still very good.

bad argument #2 to 'setmetatable' (nil or table expected)?

I currently stuck on this with a corona app I'm creating.
I have a file structure like below:
App -> Classes -> Objects -> Ships
In the App folder is the main.lua, menu.lua, level.lua and Class.lua. In the Classes folder there is Object.lua. In Objects, ship.lua and finally in the Ships are my different ships i.e. player and enemy.
I followed this tutorial and my code is almost completely identical to his (bar player and enemys classes), but still am receiving this error in the Class.lua is
"bad argument #2 to 'setetatable'(nil or table expected)"
The code I receive the error on is
function Class(Super)
Super = Super or Base
local prototype = setmetatable({}, Super) -- receive error here
prototype.class = prototype
prototype.super = Super
prototype.__index = prototype
return prototype
end
Base = Class()
function Base:new(...)
local instance = setmetatable({}, self)
instance:initialize(...)
return instance
end
function Base:initialize() end
function Base:get()
local Instances = self.Instances
if (not Instances[1]) then local obj = self:new() end
return table.remove(Instances, 1)
end
function Base:dispose()
table.insert(self.Instances, self)
end
I've tried changing the classes and changing the "setmetatable({},Super)" to "setmetatable(Super, self), putting all the classes in one file, I've read the lua docs, requiring the Class.lua in the mai, menu and the level.lua etc. and nothing has worked.
Any help would be greatly appreciated.
Thanks
function Class(Super)
Super = Super or Base
local prototype = setmetatable({}, Super) -- receive error here
prototype.class = prototype
prototype.super = Super
prototype.__index = prototype
return prototype
end
Base = Class()
Follow the execution of the code above.
You declare a function Class and then call it (and assign its returned value to Base).
Step through the execution of Class from the Base = Class() line.
function Class(Super)
The function takes one argument named Super
Super = Super or Base
You are allowing the Super argument to be nil/unpassed by using a default value of Base.
This call Base = Class() is not passing a value so this line Super = Super or Base has Super as nil and so evaluates to Super = nil or Base however the global Base is also nil as it has not yet been assigned to so you get Super = nil.
local prototype = setmetatable({}, Super)
This line then attempts to use Super (assigned from the line before) only it is, as we just saw, nil hence your error.
The bit from the tutorial that you missed (or at least missed in your posted snippet) is the crucially important local Base line above the Class function definition.

When to use the trait Instance() constructor, and questions about the traitsUI tutorial code

I have a question regarding the traitsui tutorial by Gael Varoquaux.
In code snippet 7 he makes a CaptureThread class for producing a thread for taking images from a camera. He also make a Camera class.
class TextDisplay(HasTraits):
string = String()
view = View(Item('string', show_label=False, springy=True, style='custom'))
class CaptureThread(Thread):
def run(self):
#self.display is set outside the class definition by the caller
self.display.string = 'Camera started\n' + self.display.string
n_img = 0
while not self.wants_abort:
sleep(0.5)
n_img += 1
self.display.string = ' %d image captured\n' % n_img \
+ self.display.string
self.display.string = 'Camera stopped\n' + self.display.string
class Camera(HasTraits):
start_stop_capture = Button()
display = Instance(TextDisplay)
capture_thread = Instance(CaptureThread)
view = View( Item('start_stop_capture', show_label=False))
def _start_stop_capture_fired(self):
if self.capture_thread and self.capture_thread.isAlive():
self.capture_thread.wants_abort = True
else:
self.capture_thread = CaptureThread()
self.capture_thread.wants_abort = False
self.capture_thread.display = self.display
self.capture_thread.start()
I have two questions about this code:
1) Why in the Camera class definition does he make capture_thread a Trait, by calling Instance(CaptureThread)? CaptureThread is just a thread class, why should we make a trait instance out of it?
2) In the CaptureThread class he makes use of a field self.display.string and of self.wants_abort. These two fields are not passed in via a constructor method, rather they are assigned outside of the class definition by the Camera class. Is this the best practise? Since if the user of the CaptureThread forgot to set these two fields, then an error would occur. Are there some sensible guidelines to know when I can assign thing like that, or I should use a constructor to assign them?
I hope that these questions make sense, and that this is the right place to ask them!
Thanks, labjunky
capture_thread = Instance(CaptureThread) doesn't make an instance of CaptureThread. It is more of a declaration that gets consumed by the Camera class when the class gets created. It tells that Camera class that it will have an attribute named capture_thread that should be an instance of CaptureThread or None and will default to None. This default lets the "test if self.capture_thread is initialized, otherwise create it" logic in _start_stop_capture_fired() a little cleaner, at least to some people's tastes.
For threading.Thread subclasses, yes, it's one idiomatic way to do it, though not the only one. Thread already has a specific __init__ implementation, and you could override it to do something else, but it is understandable that the author would avoid doing so in this case.
This is not the idiomatic way to initialize HasTraits subclasses which is indeed to use keyword arguments.

Using abstract classes in Matlab (without properties)

Let we have one abstract class:
classdef ACalculation < handle
methods (Abstract)
[result] = calculate (this, data);
plot (this, data, limX, limY);
end
end
And some other classes that implements ACalculation
classdef Maximum < ACalculation
methods
function [result] = calculate (this, data)
%...
end
function plot (this, data, limX, limY)
%...
end
end
To functions of implementation class i give all needed information, so i don't need any properties.
So it looks like I need static classes. But if I have static classes I have a problem with calling this functions.
I'd like to do something like that:
criteria = Maximum();
%......
result = criteria.calculate(data);
Is it bad way to use inheritance?
Should I ignore matlab advices to change functions to static?
What else could I do here?
I think that in this case, static interface implementation is quite a good pattern.
Define your classes in the following way:
classdef ACalculation < handle
methods (Abstract,Public,Static)
[result] = calculate (data);
plot (data, limX, limY);
end
end
classdef Maximum < ACalculation
methods (Public,Static)
function [result] = calculate (data)
%...
end
function plot (data, limX, limY)
%...
end
end
Then, you can write a function that expects an ACalculation type:
function foo(acalc,data)
assert(isa(acalc,'ACalculation'));
acalc.calculate(data);
acalc.plot(data,[100 200]);
end
Then create a Maximum empty instance and pass it to foo:
foo ( Maximum.empty(0), [1 2 3]);
If you want to change the calculation method, call
foo ( Minimum.empty(0), [1 2 3]);
When you say that such a pattern will not work, you are thinking like Java/C#/C++ developer. But unlike in C++ where static and virtual keyword cannot coexist, Matlab has no such limitation, because everything is done at runtime, and an "instance" can be empty or an array of n elements.
If calculate is a static method of Maximum‘, you would use ‘result = Maximum.calculate(data) to call it, without instantiating to criteria.
It's not (necessarily) a bad way to use inheritance, or bad advice from MATLAB.

Can properties of an object handle returned from a function be used without first assigning to a temporary variable?

I have a function that returns a handle to an instantiated object. Something like:
function handle = GetHandle()
handle = SomeHandleClass();
end
I would like to be able to use the return value like I would if I was writing a program in C:
foo = GetHandle().property;
However, I get an error from MATLAB when it tries to parse that:
??? Undefined variable "GetHandle" or class "GetHandle".
The only way I can get this to work without an error is to use a temporary variable as an intermediate step:
handle = GetHandle();
foo = handle.property;
Is there a simple and elegant solution to this, or is this simply impossible with MATLAB's syntax?
To define static properties, you can use the CONSTANT keyword (thanks, #Nzbuu)
Here's one example from MathWorks (with some errors fixed):
classdef NamedConst
properties (Constant)
R = pi/180;
D = 1/NamedConst.R;
AccCode = '0145968740001110202NPQ';
RN = rand(5);
end
end
Constant properties are accessed as className.propertyName, e.g. NamedConst.R. The values of the properties are set whenever the class is loaded for the first time (after the start of Matlab, or after clear classes). Thus, NamedConst.RN will remain constant throughout a session as long as you don't call clear classes.
Hmm, I don't like to disagree with Jonas and his 21.7k points, but I think you can do this using the hgsetget handle class instead of the normal handle class, and then using the get function.
function handle = GetHandle()
handle = employee();
end
classdef employee < hgsetget
properties
Name = ''
end
methods
function e = employee()
e.Name = 'Ghaul';
end
end
end
Then you can use the get function to get the property:
foo = get(GetHandle,'Name')
foo =
Ghaul
EDIT: It is not excactly like C, but pretty close.
The only way to have a static property in MATLAB is as a constant:
classdef someHandleClass < handle
properties (Constant)
myProperty = 3
end
end
then someHandleClass.myProperty will return 3.