I am trying to run an OOP program in octave originally written for Matlab. I am not able to get most of the part right but not able to call methods.
Here's the sample code.
obj = Motor('SamplePeriod', 1/256, 'Beta');
methods(obj)
Methods for class Motor:
Motor Update
obj.Update();
error: invalid index for class
I tried reading the manual, couldn't get the instruction. Also there aren't any samples online as well.
As described here, you need to use the alternate way to call your method:
m = motor(...)
p = power(m, ...)
In your case that would be
Update(obj)
As mentioned by #Daniel
You can still call a method of a class using obj.Update() syntax, but you need to implement a special method in your class:
function varargout = subsref (obj, idx)
persistent __method__ method4field typeNotImplemented
if isempty(__method__)
__method__ = struct();
__method__.Update = #(o,varargin) Update (o, varargin{:});
# Error strings
method4field = "Class #s has no field #s. Use #s() for the method.";
typeNotImplemented = "#s no implemented for class #s.";
end
method = idx(1).subs;
if ~isfield(__method__, method)
error('Unknown method #s.',method);
else
fhandle = __method__.(method);
end
if strcmp (idx(2).type, '()')
args = idx(2).subs;
if isempty(args)
out = fhandle (obj);
else
out = fhandle (obj, args{:});
end
varargout{1} = out;
end
endfunction
More details can be found inside geometry package, look into inst/io/#svg folder.
Related
I want to run jobs in Matlab using batch, with parcluster. each job should use an existing class, and run one of it's methods. I can make It work without parcluster, but with parcluster I get an error.
without parpool, this works:
define a class with a simple method:
classdef myclass
properties
prop;
end
methods
% constructor
function obj = myclass()
obj.prop = 0;
end
% add function
function obj = add(obj,a)
obj.prop = obj.prop + a;
end
end
end
create an object and use it's function:
obj = myclass();
obj = add(obj,1);
this works. but when I try to run the same thing in batch I get an error. here is what I'm doing:
c = parcluster();
j = batch(c,#myclass,1,{});
wait(j);
r = fetchOutputs(j);
obj = r{1};
j = batch(c,#add,1,{obj,1});
the last line gives an error:
warning unable to calculate the dependencies of the files:
add
because: file, function or class "add" may not exist.
how can I run class methods in batch?
The most robust way of specifying a method of a class in an anonymous function is to use the dot notation
B = batch(c, #obj.add, 1, {1});
wait(B)
%// Re-assign results to obj (see note below)
obj = fetchOutputs(B);
This helps MATLAB to resolve myclass.add better as it is more explicit. The way that you had written it previously, MATLAB is looking for a regular function named add and is unable to find it. It does not consider the types of the input (which in your case would be required to know that it is a method).
Note: batch will make a copy of your object when you pass it as an input. Because of that, you will need to explicitly grab the output and re-assign to obj because the original obj will not be modified in-place.
Dear lovely community,
I already looked in Google and in the forum and also found some interesting posts. But in the end I still didn't get it worked. So, I am going to post the question here. I know in Matlab are already get/ Set methods implemented, but I am using objects and therefore I didn't understand where to implement them.
Overall Structure:
+Measurement\MeasurerIF
+Measurement\MeasurerComponent
In my Interface I declare my functions I want to implement and this Interface is furthermore abstract. It looks like this:
classdef MeasuererIF < handle
methods (Abstract=true)
getStatus(cObj) ;
setStatus(cObj,iStatus) ;
getInfo(cObj) ;
setInfo(cObj,sInfo) ;
end
end
Then I created the other class MeasurerComponent in which I implemented the methods and also the constructor:
classdef MeasurerComponent < PerformanceMeasurement.MeasuererIF
%% MeasurerComponent: Evaluates which model is used and contains them as childs.
% Detailed explanation goes here
properties (Access=protected)
miStatus;
msInfo;
mcData;
end
methods
%constructor
function cObj = PerformanceMeasurement.MeasurerComponent ;
cObj.miStatus = -1 ;
cObj.msInfo = 'Import' ;
cObj.mcData = [] ;
end
%Status
function setStatus(cObj,iStatus)
cObj.miStatus = iStatus;
end
function iStatus = getStatus(cObj)
iStatus = cObj.miStatus;
end
%Info
function setInfo(cObj,sInfo)
cObj.msInfo = sInfo;
end
function sInfo = getInfo(cObj)
sInfo = cObj.msInfo ;
end
end
end
Earlier I just used the getMethods and recently added the setMethods and now it doesn't work anymore. The Problem is that when I create an object
obj = Measurement.MeasurerComponent
the programm doesn't initialize the values anymore.
For a = obj.getInfo;
I receive just []
Does someone has an idea why it doesn't get initialized anymore? After I received a tip I changed the initialization process to the constructor due to the handle class.
I am really thankful and glad about each hint and tip!
Cheers
Your constructor should be defined by function cObj = MeasurerComponent, without the PerformanceMeasurement prefix. This is just the way that packages are defined and used in Matlab - you add the prefix if using the class from outside the package, but not within the package (explained here: "Note that definitions do not use the package prefix" -
http://uk.mathworks.com/help/matlab/matlab_oop/scoping-classes-with-packages.html?refresh=true).
Also, you have a typo - your abstract parent class file is called +Measurement\MeasurerIF but in the definition you spell it MeasuererIF. It doesn't matter which one it is called, but the name of the class does have to match the filename!
If I correct both of these issues, then your code becomes
+Measurement\MeasurerIF
classdef MeasurerIF < handle
methods (Abstract=true)
getStatus(cObj)
setStatus(cObj,iStatus)
getInfo(cObj)
setInfo(cObj,sInfo)
end
end
+Measurement\MeasurerIF
classdef MeasurerComponent < Measurement.MeasurerIF
%% MeasurerComponent: Evaluates which model is used and contains them
%% as childs.
properties (Access=protected)
miStatus
msInfo
mcData
end
methods
%constructor
function cObj = MeasurerComponent
cObj.miStatus = -1 ;
cObj.msInfo = 'Import' ;
cObj.mcData = [] ;
end
%Status
function setStatus(cObj,iStatus)
cObj.miStatus = iStatus;
end
function iStatus = getStatus(cObj)
iStatus = cObj.miStatus;
end
%Info
function setInfo(cObj,sInfo)
cObj.msInfo = sInfo;
end
function sInfo = getInfo(cObj)
sInfo = cObj.msInfo ;
end
end
end
and if I type the following:
obj = Measurement.MeasurerComponent;
obj.getInfo
then I get back
ans =
Import
which is what I expect.
We have this code in 'Reconstruction the subclass object from a saved struct' from MATLAB OOP documentation.
classdef MySuper
% Superclass definition
properties
X
Y
end
methods
function S = saveobj(obj)
% Save property values in struct
% Return struct for save function to write to MAT-file
S.PointX = obj.X;
S.PointY = obj.Y;
end
function obj = reload(obj,S)
% Method used to assign values from struct to properties
% Called by loadobj and subclass
obj.X = S.PointX;
obj.Y = S.PointY;
end
end
methods (Static)
function obj = loadobj(S)
% Constructs a MySuper object
% loadobj used when a superclass object is saved directly
% Calls reload to assign property values retrived from struct
% loadobj must be Static so it can be called without object
obj = MySuper;
obj = reload(obj,S);
end
end
end
I have a question about obj = MySuper. What is purpose of this line? How we can call MySuper object from this function without insert any object to loadobj function?
You first question is: What is the purpose of the obj = MySuper; line?
The answer is that the obj = MySuper; line initiates the variable obj as an element of the class MySuper. Non-static functions in a class will only run if the first input parameter is an instance of the class, so if obj is not initiated as a MySuper-object, then matlab will look for other functions called reload to run, and if none is found give you an error.
For your second question, I am not 100% sure what you mean. But I hope one of the following points will answer your question:
If you want to make a function that relates to a class, but not to a specific instance of the class, you can make a static function, these can take any input (also (if you want it that way) no input at all) - that is they don't need to have a first input parameter of the specific class.
To run a static function, use the class name followed by a dot and then the function name, so here you would type MySuper.loadobj(S) to run the function with the parameter S.
I would suggest that you try this out with the given example to better get to know the way oop works in matlab, you may for example try:
S.PointX = 1;
S.PointY = 2;
obj = MySuper.loadobj(S)
I hope this answers your questions.
I am using
fid = fopen('fgfg.txt');
to open a file.
Sometimes an error occurs before I manage to close the file. I can't do anything with that file until I close Matlab.
How can I close a file if an error occurs?
First of all, you can use the command
fclose all
Secondly, you can use try-catch blocks and close your file handles
try
f = fopen('myfile.txt','r')
% do something
fclose(f);
catch me
fclose(f);
rethrow(me);
end
There is a third approach, which is much better. Matlab is now an object-oriented language with garbage collector. You can define a wrapper object that will take care of its lifecycle automatically.
Since it is possible in Matlab to call object methods both in this way:
myObj.method()
and in that way:
method(myObj)
You can define a class that mimics all of the relevant file command, and encapsulates the lifecycle.
classdef safefopen < handle
properties(Access=private)
fid;
end
methods(Access=public)
function this = safefopen(fileName,varargin)
this.fid = fopen(fileName,varargin{:});
end
function fwrite(this,varargin)
fwrite(this.fid,varargin{:});
end
function fprintf(this,varargin)
fprintf(this.fid,varargin{:});
end
function delete(this)
fclose(this.fid);
end
end
end
The delete operator is called automatically by Matlab. (There are more functions that you will need to wrap, (fread, fseek, etc..)).
So now you have safe handles that automatically close the file whether you lost scope of it or an error happened.
Use it like this:
f = safefopen('myFile.txt','wt')
fprintf(f,'Hello world!');
And no need to close.
Edit:
I just thought about wrapping fclose() to do nothing. It might be useful for backward compatibility - for old functions that use file ids.
Edit(2): Following #AndrewJanke good comment, I would like to improve the delete method by throwing errors on fclose()
function delete(this)
[msg,errorId] = fclose(this.fid);
if errorId~=0
throw(MException('safefopen:ErrorInIO',msg));
end
end
You can try a very neat "function" added by ML called onCleanup. Loren Shure had a complete writeup on it when it was added. It's a class that you instantiate with your cleanup code, then it executes when it goes out of scope - i.e. when it errors, or the function ends. Makes the code very clean. This is a generic version of the class that Andrey had above. (BTW, for complex tasks like hitting external data sources, custom classes are definitely the way to go.)
from the help:
function fileOpenSafely(fileName)
fid = fopen(fileName, 'w');
c = onCleanup(#()fclose(fid));
functionThatMayError(fid);
end % c executes fclose(fid) here
Basically, you give it a function handle (in this case #()fclose(fid))that it runs when it goes out of scope.
Your cleanup code is executed either when an error is thrown OR when it exits normally, because you exit fileOpenSafely and c goes out of scope.
No try/catch or conditional code necessary.
Andrey's solution above is indeed the best approach to this problem. I just wanted to add that throwing an exception in method delete() might be problematic, if you deal with arrays of safefopen objects. During destruction of such an array, MATLAB will call delete() on each array element and, if any delete() throws, then you might end up with leftover open file handles. If you really need to know whether something went wrong during destruction then issuing a warning would be a better option IMHO.
For those that feel lazy to write all the forwarding methods to every MATLAB builtin that uses file handles, you may consider the simple alternative of overloading method subsref for class safefopen:
methods(Access=public)
function varargout = subsref(this, s)
switch s(1).type
case '.'
if numel(s) > 1,
feval(s(1).subs, this.fid, s(2).subs{:});
else
feval(s(1).subs, this.fid);
end
% We ignore outputs, but see below for an ugly solution to this
varargout = {};
otherwise
varargout{1} = builtin('subsref', this, s);
end
end
end
This alternative uses the somewhat ugly feval, but has the advantage of working even if the MATLAB guys (or yourself) decide to add new functions that involve file handles, or if the number/order of the input arguments to a given function change. If you decide to go for the subsref alternative then you should use class safefopen like this:
myFile = safefopen('myfile.txt', 'w');
myFile.fprintf('Hello World!');
EDIT: A disadvantage of the subsref solution is that it disregards all output arguments. If you need the output arguments then you will have to introduce some more ugliness:
methods(Access=public)
function varargout = subsref(this, s)
if nargout > 0,
lhs = 'varargout{%d} ';
lhs = repmat(lhs, 1, nargout);
lhs = ['[' sprintf(lhs, 1:nargout) ']='];
else
lhs = '';
end
switch s(1).type
case '.'
if numel(s) > 1,
eval(...
sprintf(...
'%sfeval(''%s'', this.fid, s(2).subs{:});', ...
lhs, s(1).subs) ...
);
else
eval(...
sprintf('%sfeval(''%s'', this.fid);', ...
lhs, s(1).subs) ...
);
end
otherwise
varargout{1} = builtin('subsref', this, s);
end
end
end
And then you could do things like:
myFile = safefopen('myfile.txt', 'w');
count = myFile.fprintf('Hello World!');
[filename,permission,machineformat,encoding] = myFile.fopen();
fids=fopen('all');
fclose(fids);
%assuming that you want to close all open filehandles
I'm working on a command line application for ultrasound simulation in MATLAB. Nearly every object in our code is a subclass of handle (to pass as references). The problem I'm having is that all the methods inherited from the handle class shows up under the "Methods" section in MATLAB (see example below).
What I want is to hide the inherited methods from the handle class so that only the function the user is allowed to use is shown under "Methods". This way it doesn't look so messy for the user if he/she wants to know which methods to use.
Example Test class:
classdef Test < handle
methods
function myFunction(obj)
end
end
end
In the command line:
T = Test()
T =
Test handle with no properties.
Methods, Events, Superclasses
After clicking on "Methods":
Methods for class Test:
Test delete findobj ge isvalid lt ne
addlistener eq findprop gt le myFunction notify
What I want:
Methods for class Test:
Test myFunction
Is this possible in MATLAB?
If you overload all of the subclass methods in a hidden methods block I think it will do exactly what you're looking for.
I'm not sure which versions of Matlab this works in, but it definitely works for me in R2012b.
The exception is isvalid as it is Sealed so you can't override it in a handle subclass.
classdef handle_light < handle
methods(Hidden)
function lh = addlistener(varargin)
lh = addlistener#handle(varargin{:});
end
function notify(varargin)
notify#handle(varargin{:});
end
function delete(varargin)
delete#handle(varargin{:});
end
function Hmatch = findobj(varargin)
Hmatch = findobj#handle(varargin{:});
end
function p = findprop(varargin)
p = findprop#handle(varargin{:});
end
function TF = eq(varargin)
TF = eq#handle(varargin{:});
end
function TF = ne(varargin)
TF = ne#handle(varargin{:});
end
function TF = lt(varargin)
TF = lt#handle(varargin{:});
end
function TF = le(varargin)
TF = le#handle(varargin{:});
end
function TF = gt(varargin)
TF = gt#handle(varargin{:});
end
function TF = ge(varargin)
TF = ge#handle(varargin{:});
end
function TF = isvalid(varargin)
TF = isvalid#handle(varargin{:});
end
end
end
If you save the above class to handle_light.m and then type methods handle_light in the command window you will get the following result:
Methods for class handle_light:
handle_light isvalid
The Test class then becomes:
classdef Test < handle_light
methods
function myFunction(obj)
end
end
end
Doing it in this way means that you don't need to put the overloads in the Test class which keeps things neater.
There is a solution here, including sample code.
In short, what you need to do is to overload Matlab's built-in function methods, so that when it is called on your class, it removes the methods of handle from the output. Make sure it works on everything else, though so that you don't mess up your user's other code. If you don't use the #foldername variant to store your class, you could put it into a private directory, for example.
Not a full solution, but if you do methods(T, '-full'), then it at least tells you which methods are inherited from handle, so you know what to ignore.
Just get the functions from the inherited class and cancel them out with the ones from the main class using setdiff.
mH = methods('handle');
m = methods('MyClass');
m = setdiff(m,mH);