I have this
classdef what
properties ( ... )
...
end
methods (Access=public)
...
end
methods
function obj = what(...) ... end % constructor
function test = Test1() ... end
function test = Test2() ... end
end
The constructor has a lot of constraints in it such that when I create the what it fails if the conditions are not met, the constraints are tested by calling Test1 and Test2.
I have stored the test functions also under methods, and I want these to be hidden so that they don't show up outside the classdef. but I get thrown an error for Test1 and Test2.
I want these Test functions to be private, hidden, and only related to this class but I also want it to be call-able when using the constructor function found in methods, My question is: what would be the 'correct' place and method to store these functions.
I am currently getting an error when I use the constructor function, however, if I add the functions in the bottom of the page outside the classdef then the functions work but I am not sure if this is good practice and why I can't have the test functions in the method section.
There are several ways to deal with this.
In general, private functions are placed inside a methods (Access = private) block. Sometimes they can also be made static, if this makes sense. Private methods can also be placed in a separate folder.
classdef what
methods % no properties here
function obj = what(varargin) % constructor
...
out = obj.Test1(in); % object method calling example
...
end
end
methods (Access = private)
function tf = Test1(varargin)
...
end
% etc ...
end
If these functions are only ever used by the constructor, you can make them nested:
classdef what
methods % no properties here
function obj = what(varargin) % constructor
...
out = Test1(in); % no need for "obj" here
...
function tf = Test1(varargin)
...
end % Test1
end % constructor
end % methods
As mentioned by Cris, you can also put functions after the classdef block:
classdef what
...
end
function tf = Test1(varargin)
end
The suggestions above should solve your problem. Now for some other comments:
It's probably not a goot idea to name your class what, as this is a name of a builtin MATLAB function.
While it is possible to set a private method block to be Hidden, this is generally not needed in order to "hide" private methods, as these are not visible outside the class anyway.
I would personally suggest sticking to a certain naming convention (e.g. Pascal or Java) (this is referring to the class name which is lowercase as opposed to the "Test" methods which are uppercase).
If you're fairly new to MATLAB OOP, you might want to read about Handle Classes.
Related
I have a containers.Map file/variable that I've defined through the Matlab Command Window (or some other script) and have saved it to directory. I'd like to be able to have an instance of my class be able to use that map without having to define it in the class definition, or with some other function that defines it each time the function is called. So I have:
myMap.mat
and in a separate myClass.m file (in the same directory) i'd like to be able to call myMap like so:
classdef myClass < handle
properties
number
end
methods
function obj = myClass(input)
obj.number = myMap(input);
end
end
end
What's the most efficient way to get myMap "into the class" so that the instance can use it? matfile has been giving me some Warnings about format not supporting partial loading, and I can't imagine load is terribly efficient. Any suggestions is appreciated.
There are many approaches you can use but, honestly, I think the simplest one would be using a persistent object in your class constructor, as follows:
classdef myClass < handle
properties
number
end
methods
function obj = myClass(input)
persistent pmap;
if (isempty(pmap))
load('map.mat','map');
pmap = map;
end
obj.number = pmap(input);
end
end
end
I would like to have a class which, in its constructor, can have knowledge (extract as a string) its instance name.
For the moment I worked the name extraction out like this:
classdef mysession
methods (Access = public)
function this=mysession (varargin)
this.cargs=varargin;
this.built=false;
end
function id=build(this)
id=this.mynameis;
this.id = id;
%% instructions needing id
built=true;
end
function name = mynameis (this)
name=evalin ('caller', 'inputname');
end
end
properties (Access=private)
id
built
cargs
end
end
which requires the ugly
A = mysession; A.build
syntax in order to work...
There is no way to get the variable name that is used to assign the output of a function or class constructor. As you've discovered, the only way to get the object's variable name in the calling workspace is to call another method of the class at which point you can use inputname to query it.
That aside, it's not clear why you need to do this but I'd strongly discourage it. Particularly with handle classes, you can have multiple variables point to the same object, therefore the object technically has multiple names.
I'm new to MATLAB OOP. I have an abstract class defining an abstract method in my matlab path. I have a subclass named SubAbsClass in a subfolder named #SubAbsClass. I cannot create an object of the subclass after implementing the abstract method in the subclass. Here's my SubAbsClass implementation:
classdef SubAbsClass < AbsClass
properties
O1
end
methods
function obj=SubAbsClass(a,b)
obj.O1=absMethod(a,b);
end
end
methods (Static)
function out = absMethod(a,b)
out = a + b;
end
end
end
and my abstract class implementation is:
classdef AbsClass
methods(Abstract, Static)
result = absMethod
end
end
when I try to create an object in the MATLAB path (the abstract class is in the MATLAB path), I get an error. I have tried many configurations and searched the matlab oop document, and also the web including stackoverflow but unfortunately couldn't find an example to implement. I appreciate your help
>> clear all; clear classes;
>> obj=SubAbsClass(5,2)
Undefined function 'absMethod' for input arguments of type 'double'.
Error in SubAbsClass (line 11)
obj.O1=absMethod(a,b);
Within a method, Matlab considers non-dot references to be calls to local functions (defined outside the classdef block within the class file) or to a function somewhere on the Matlab path following the usual look-up rules.
So you need to call the Static method via the instance obj in the constructor:
methods
function obj = SubAbsClass(a,b)
obj.O1 = obj.absMethod(a,b);
end
end
One little caveat to the above is that non-Static methods also have a functional form.
So if the method was not Static, this notation would also work
methods
function obj = SubAbsClass(a,b)
obj.O1 = absMethod(obj,a,b);
end
end
Which, I think, is almost equivalent to the dot notation, although it has been said to be "generally" faster (albeit, that was four years ago).
Here are the details for ordinary method invocation and Static method invocation.
I'm trying to write a class that wraps around a serial port to read a sensor:
classdef sensor < handle
properties
Value
s
end
methods
function obj = sensor(port)
obj.s = serial(port);
obj.s.BytesAvailableFcn = #(o,e) obj.getData;
fopen(obj.s);
end
function delete(obj)
disp('called destructor');
try
fclose(obj.s);
delete(obj.s);
end
end
function getData(obj)
obj.Value = fscanf(obj.s, '%d');
end
end
end
When I try to clear the workspace, the destructor never gets called:
>> foo = sensor('COM1');
>> clear foo % should disp() something!
Based on my previous experiences, there must still be a reference to foo. Turns out this is embedded in the serial port foo.s:
>> ports = instrfindall;
>> ports.BytesAvailableFcn
ans =
#(o,e)obj.getData
Once I clear out the BytesAvailableFcn, i.e.,
>> ports.BytesAvailableFcn = '';
and then clear all, I get my called destructor displayed.
How can I break this circular reference and get my destructor to get called? If the destructor doesn't get called, the serial port stays bound.
The problem is not quite that you have a circular reference; MATLAB should in theory catch those. The issue is that the circular reference goes via Java, and MATLAB can't catch it.
In more detail - your serial object contains a Java object internally, which is the real thing that captures the connection to the serial port. When you set its callback, MATLAB sets the callback of the underlying Java object. If the callback is to a method of an object that contains the serial object as a property, then you have a circular reference that goes via the underlying Java object. When you call clear, MATLAB checks for circular references, and if they were all in only MATLAB it would catch them, and call the destructor - but it doesn't catch them as it goes via Java.
One solution is to explicitly call the destructor, and perhaps that's not too much trouble.
Another workaround might be to simply not have the callback as a method of the class - perhaps it could just be a regular function, as it doesn't really seem to need any information from the main object itself other than the reference to the serial object. If you would prefer to keep all the code in a single file, perhaps you could create it as an anonymous function (although be careful, as an anonymous function will capture the workspace that it's created in, which depending on where you create it may include a reference to the main object, in which case you'd have a circular reference again.
Edit: Rody's right - my apologies, I read the problem too fast and didn't notice that getData actually sets the Value property rather than just returning the data. Rody's solution in his answer may be an alternative workaround, but like he says - yuck. I'd just call delete manually.
Intriguing problem! :)
I found a workaround, but it's not going to be pretty.
You cannot use an anonymous function. That would capture the local workspace, which will contain a reference to obj. You'll have to use one level of indirection (to a Static method, otherwise, you'd have the same problem).
This static method can safely return a function handle. This function handle is to a function, which has to be passed the instrument object.
Setting the Value property is of course impossible without passing a reference to the object, so, you'll have to create a global state in the function, a variadic call signature, and a getter for the Value property.
I have the feeling I've over-engineered this a bit (it's Friday after all), so if anyone sees a simpler way, please correct me. Anyway, here's what I mean:
classdef sensor < handle
properties
s
end
properties (Dependent)
Value
end
methods
function obj = sensor(port)
obj.s = serial(port);
% You cannot use function handle without implicitly passing obj into
% it. Instead, get a function handle from another function, one that
% does not have this problem:
obj.s.BytesAvailableFcn = sensor.getGetData(obj.s);
fopen(obj.s);
end
function delete(obj)
disp('called destructor');
try %#ok<TRYNC>
fclose(obj.s);
delete(obj.s);
end
end
% Use a getter for Value, so that whenever you query the Value property,
% you get the most recently read sensor data
function V = get.Value(obj) %#ok<MANU>
V = getData();
end
end
% Use indirection to a Static method, to avoid referencing obj implicitly
methods (Access = private, Static)
function f = getGetData(S)
f = #(o,e)getData(S);
end
end
end
% The actual sensor reader
function data = getData(S)
persistent port
if nargin == 1
port = S; return; end
try
data = fscanf(port, '%d');
catch ME
% ...
end
end
Just....yuck.
I'm new to matlab classes and have just gone through a couple tutorials and now am trying to make one. In my methods section however, I'm having trouble with what I've been trying to do. The object should only need a single piece of info to construct the remaining properties which I will pass as input to the constructor. I was then thinking that I should be able to call two more functions in the methods section to fill in the remaining properties... see pseudocode below...
methods
function obj=myConstructor(input)
obj.property1=input;
getProperty2(obj);
getProperty3(obj);
end
function getProperty2(obj)
obj.property2 = do something and save in property2...
end
function getProperty3(obj)
obj.property3 = do something and save in property3...
end
end
However, when I try and run this, neither property 2 or 3 are assigned... only the value that I pass to the constructor. Any help/ideas on how to accomplish the initialization would be much appreciated. Thanks.
First of all, get methods are usually used to retrieve (i.e. get) the value of a property of an object. Not to calculate something.
Next, the MATLAB object model has two different kinds: value objects and handle objects. The distinction is important, but as you don't mention any, I will assume you are using value objects. The behavior for handle objects is totally different.
In contrast to e.g. Java and most other languages, you need to return the changed object. So in MATLAB this would be something like:
classdef MyClass
properties
p1, p2, p3;
end
methods
function obj = MyClass(input)
obj.p1 = input;
obj = obj.calculateP2(input);
obj = obj.calculateP3(input);
end
function obj = calculateP2(obj, input)
obj.p2 = someLengthyCalculation(input);
end
function obj = calculateP3(obj, input)
obj.p3 = someOtherLengthyCalculation(input);
end
end
end
This can be made more clean, as most likely the calculateP? methods belong better as private static methods. This all depends on how much you want to pass to these methods.