So if I have an Object and needs to call one method from another within that Object, how do I construct that call?
TestObject = {}
TestObject.__index = TestObject
function TestObject.new()
local self = setmetatable({}, TestObject)
self.value = init
-- a count [integer] of something. Not important what
self.counter = 99
return self
end
function TestObject:getCount()
return self.counter
end
function TestObject:getCountPlus(add_value)
-- HERE HOW SHOULD THIS BE FORMATED??
return self.getCount() + add_value
end
And using this Object would be something like this:
local testObject = TestObject.new()
testObject:getCountPlus(1)
which should result in 100.
The getCount() needs to know what instance it is in. When you write
function TestObject:getCount()
it is same as writing
function TestObject.getCount(self)
(note the colon changed to dot). So calling self.getCount() is like calling getCount with self=nil. Do self:getCount(), which is same as self.getCount(self). This may seem odd: why does interpreter not provide self automatically? It's just the way the language was designed: it only provides self automatically with the : notation.
Related
So lots of languages have a pattern where you do something like this:
object = Create_Object().Set(1).Set(2).Set(3);
(I believe this originated in Smalltalk.) This works because the Set() method returns a reference to its receiver.
Can I do anything like this in Ada?
Approaches I've tried which don't work include:
-- doesn't work because the returned object is a read-only copy of the receiver
function Set(self: in out Object) return Object;
-- doesn't work because I can't return an access to a local variable
function Set(self: in out Object) return access Object;
-- looks like it works until I realise that it's not a method, and isn't doing
-- dynamic dispatch [*]
function Set(self: access Object) return access Object;
Can this be done?
I think a function with this profile will do the job for you:
function Set (Target : in Instance;
New_Item : in Integer) return Instance;
Having written a full package around that function declaration, I can write:
Object := Set (1).Set (2).Set (3);
Object.Show;
and get the output:
{1, 2, 3}
I've pushed the full sources to http://repositories.jacob-sparre.dk/miscellaneous-ada-2005-examples/.
Your third proposal is the correct approach, and you are in fact defining a primitive operation when you type "access" for the parameter. Here is an example, which uses two tagged types to show where dispatching occurs, and uses chaining of method calls. I have provided a procedure for convenience, as well, since otherwise you would have to use a temporary variable. I have used Create_Object, but an explicit call to "new", but that's of course the same thing. In addition, I have shown an example where Ada will not do dynamic dispatching when it knows statically the types involved. This is actually a nice features (performance-wise), even if indeed it requires care (and even experts are bitten every now and then :=)
with Utils; use Utils;
procedure Chain is
O : access Object := new Object;
C : access Child := new Child;
begin
O.Add (1).Add (2);
C.Add (3).Add (4);
end Chain;
package Utils is
type Object is tagged null record;
function Add (Self : access Object; Val : Integer) return access Object;
procedure Add (Self : access Object; Val : Integer); -- for convenience
type Child is new Object with null record;
overriding function Add (Self : access Child; Val : Integer) return access Child;
overriding procedure Add (Self : access Child; Val : Integer); -- for convenience
end Utils;
with Ada.Text_IO; use Ada.Text_IO;
package body Utils is
function Add (Self : access Object; Val : Integer) return access Object is
begin
Put_Line ("func Object.Add" & Val'Img);
Self.Add (Val); -- static call, not dynamic dispatch
return Self;
end Add;
procedure Add (Self : access Object; Val : Integer) is
begin
Put_Line ("proc Object.add" & Val'Img);
end Add;
overriding function Add (Self : access Child; Val : Integer) return access Child is
begin
Put_Line ("Child.Add" & Val'Img);
Self.Add (Val); -- static call, not dynamic dispatch
return Self;
end Add;
overriding procedure Add (Self : access Child; Val : Integer) is
begin
Put_Line ("proc Child.Add" & Val'Img);
end Add;
end Utils;
The output of this program is:
func Object.Add 1
proc Object.add 1
proc Object.add 2
Child.Add 3
proc Child.Add 3
proc Child.Add 4
Edit: As discussed in the comments, it is recommended to always use overriding to make sure the procedure is indeed overriding, not using a different profile. An access parameter does create a primitive operation.
From paragraph 18, function [formal] parameters can only use mode 'in' (read-only). So the input object does not get modified.
18 {parameter mode} The parameter mode of a formal parameter conveys the direction of information transfer with the actual parameter: in, in out, or out. Mode in is the default, and is the mode of a parameter defined by an access_definition. The formal parameters of a function, if any, shall have the mode in. [Ada 2005]
So I do not think that the language supports it as shown in other languages.
However, if you don't mind copies, we can save the result back in the object, but that's not the same as those other languages that you reference.
obj := obj.set("this").set(123).set(some_other_type);
You set "this" on a copy of 'obj' and return that copy. From that copy, we create a new copy and set 123 in that copy, which is in turn returned. Finally, that last result is copied and we set 'some_other_type' to it. That last copy is returned and we can save it in obj. Note that a well optimized implementation can avoid most if not all of those copies if the set() functions are small enough and inlined, but I would not could on it.
In retrospect, using procedures:
obj.set("this");
obj.set(123);
obj.set(some_other_type);
will do no copies at all.
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.
Confer the following code:
classdef highLowGame
methods(Static)
function [wonAmount, noGuesses] = run(gambledAmount)
noGuesses = 'something';
wonAmount = highLowGame.getPayout(gambledAmount, noGuesses); % <---
end
function wonAmount = getPayout(gambledAmount, noGuesses)
wonAmount = 'something';
end
end
end
Is there a way to call a static method of the same class (inside a static) method without having to write the class name? Something like "self.getPayout(...)" - in case the class turns out to get to 500 lines and I want to rename it.
Not an answer to your question directly, but it's worth noting that you can also put "local functions" after the end of your classdef block in your class.m file, and these behave like private static methods, but you do not need to invoke them using the class name. I.e.
% myclass.m
classdef myclass
methods ( Static )
function x = foo()
x = iMyFoo();
end
end
end
function x = iMyFoo()
x = rand();
end
% end of myclass.m
As far as I can tell, "no" with a "but". In general, you can only specify the static method with the class name. However, you can fake your way around the restriction since MATLAB has feval:
classdef testStatic
methods (Static)
function p = getPi() %this is a static method
p = 3.14;
end
end
methods
function self = testStatic()
testStatic.getPi %these are all equivalent
feval(sprintf('%s.getPi',class(self)))
feval(sprintf('%s.getPi',mfilename('class')))
end
end
end
Here, class(self) and mfilename both evaluate to 'testStatic', so the functions above end up evaluating 'testStatic.getPi'.
Or, alteratively, you can write a non-static method, self.callStatic; then always use that. Inside that, just call testStatic.getPi. Then you'll only need to change that one line.
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.
I'm trying to grab a method handle from within an object in MATLAB, yet something in the sort of str2func('obj.MethodName') is not working
The answer is to get a function handle as #Pablo has shown.
Note that your class should be derived from the handle class for this to work correctly (so that the object is passed by reference).
Consider the following example:
Hello.m
classdef hello < handle
properties
name = '';
end
methods
function this = hello()
this.name = 'world';
end
function say(this)
fprintf('Hello %s!\n', this.name);
end
end
end
Now we get a handle to the member function, and use it:
obj = hello(); %# create object
f = #obj.say; %# get handle to function
obj.name = 'there'; %# change object state
obj.say()
f()
The output:
Hello there!
Hello there!
However if we define it as a Value Class instead (change first line to classdef hello), the output would be different:
Hello there!
Hello world!
One could also write
fstr = 'say';
obj.(fstr)();
This has the advantage that it does not require a handle class to work if the object (obj) is modified.
Use #. The following code works for me:
f = #obj.MethodName
No other answer mimics str2func('obj.MethodName'). Actually, this one doesn't either, not exactly. But you can define an auxillary function like so:
function handle = method_handle(obj, mstr)
handle = #(varargin) obj.(mstr)(varargin{:});
end
Then method_handle(obj, 'MethodName') returns a handle to obj.MethodName. Unfortunately, you cannot pass the variable name of obj as a string - eval("obj") will be undefined in the function's scope.