MATLAB: Fix for accessing other properties in set function [duplicate] - matlab

I have a class which has some properties and 2 are related, in the example called param1, param2. They are independent, just constrained. param2 must be as large or larger than param1 and must always exist if param1 does. Code in question is something like:
function set.param1(obj, input)
disp('setting param1')
obj.param1 = input;
if (isempty(obj.param2) || obj.param2 < obj.param1) % Warning on param2
obj.param2 = obj.param1; % Warning on param2
end
end
Similar code for the set.param2.
Code works fine and I cannot see any better way to do it. The problem - it produces warning "a set method..." like mentioned in title. I suppressed them for the lack of better solution.
Is there a better way to achieve this functionality and without warnings? Obviously not a hacky "solution" like a hidden function SetParam2:
function SetParam2(obj, input)
obj.param2 = input;
end
which confuses editor just enough it doesn't complain.

You could use two layers of properties
one layer which is exposed and Dependent
one layer which is private and actually stores the values
The similar technique is used here in the documentation: Avoid Property Initialization Order Dependency.
classdef TestClass < handle
properties (Access = private)
privateParam1;
privateParam2;
end
properties (Dependent)
param1;
param2;
end
methods
function p1 = get.param1(obj)
p1 = obj.privateParam1;
end
function p2 = get.param2(obj)
p2 = obj.privateParam2;
end
function set.param1(obj, input)
obj.privateParam1 = input;
if (isempty(obj.privateParam2) || obj.privateParam2 < obj.privateParam1)
obj.privateParam2 = obj.param1;
end
end
function set.param2(obj, input)
if (~isempty(obj.privateParam1) && obj.privateParam1 > input)
obj.privateParam2 = obj.privateParam1;
else
obj.privateParam2 = input;
end
end
end
end
The trick here: privateParam1 and privateParam2 stores the two values. The get and set only implemented for the exposed properties param1 and param2: the get returns simply the inner property and in the set both of them can be used without the analyzer warning as they are marked as Dependent.

Related

Program in same OOP style as App Designer

I like the OO programming style that matlabs App Designer uses (or at least the way I'm using it). Now I'm wondering if I can use the same style in my "normal" matlab class.
What I have now:
classdef myClass
properties
myVar;
end
methods
function Main(obj)
obj.myVar = "a";
obj = DoSomething(obj);
disp(obj.myVar) % outputs "c"
end
function obj = DoSomething(obj)
if(obj.myVar == "a")
obj.myVar="c";
else
obj.myVar = "b";
end
end
end
end
Which can be called externally using:
myClassInst = myClass;
myClassInst.Main()
I would like to get rid of all the "obj = " in the classdef, as is possible in App Designer. So something that would look like this:
classdef myClass
properties
myVar;
end
methods
function Main(obj)
obj.myVar = "a";
DoSomething(obj); % Just call the function without "obj = "
disp(obj.myVar) % outputs "a" because I didn't overwrite obj
end
function DoSomething(obj)
if(obj.myVar == "a")
obj.myVar="c";
else
obj.myVar = "b";
end
end
end
end
The equivalent of this seems to work in App Designer. So it appears you can modify variables in a class (instance?) in App Designer, while also being able to access the modified variable without explicitly overwriting your old class instance.
I noticed App Designer has all methods an properties set to (Access = private), though I'm not sure that has anything to do with it. Of course if I set everything to private, then I can't access the Main() method from outside anymore.
So my question is, how can I program in "normal" matlab, the same way as is possible in App Designer?
EDIT:
The following works in App Designer (I left out the methods/properties for the GUI elements):
classdef tmp < matlab.apps.AppBase
properties (Access = private)
myVar; % Description
end
methods (Access = private)
function doSomething(app)
if app.myVar == "a"
app.myVar = "c";
else
app.myVar = "b";
end
end
end
% Callbacks that handle component events
methods (Access = private)
% Code that executes after component creation
function startupFcn(app)
app.myVar = "a";
doSomething(app);
disp(app.myVar); % outputs "c"
end
end
end
You definitely can! All you have to do is inherit from the handle class, as opposed to a value class which is the default for matlab. You can also define private and public methods as in other languages.
The only thing you have to do is:
classdef myclass < handle % this is how you inherit from base class
properties
public_property
end
properties (Access=private)
private_property
end
methods
function obj = myclass() % class constructor
...
end
function public_function()
...
end
end
methods (Access=private)
function private_function()
...
end
end
end
Now every time you pass an object of this class to a function, you are not passing it by value, you are passing by reference (as you might be used to from python) and modifying it's properties modifies them also in the original object.
You need to inherit (< at the top of the class) from a handle class
classdef myClass < handle
properties
var
end
methods
function obj = myClass( varargin )
% Constructor function, called automatically when object is created
end
function someFunction( obj )
obj.randomizeVar(); % Equivalent to randomizeVar( obj );
end
function randomizeVar( obj )
obj.var = rand();
end
end
end
See the documentation for the difference between a "handle" and "value" class:
A value class constructor returns an object that is associated with the variable to which it is assigned. If you reassign this variable, MATLABĀ® creates an independent copy of the original object. If you pass this variable to a function to modify it, the function must return the modified object as an output argument. For information on value-class behavior, see Avoid Unnecessary Copies of Data.
A handle class constructor returns a handle object that is a reference to the object created. You can assign the handle object to multiple variables or pass it to functions without causing MATLAB to make a copy of the original object. A function that modifies a handle object passed as an input argument does not need to return the object.
Moreover, if you edit matlab.apps.AppBase, the class which you app designer code inherits, you can see that the first line is
classdef AppBase < handle
So you are literally doing the same thing, without the AppBase middle-man.

Avoid warning "a set method for non-dependent property should not access ..."

I have a class which has some properties and 2 are related, in the example called param1, param2. They are independent, just constrained. param2 must be as large or larger than param1 and must always exist if param1 does. Code in question is something like:
function set.param1(obj, input)
disp('setting param1')
obj.param1 = input;
if (isempty(obj.param2) || obj.param2 < obj.param1) % Warning on param2
obj.param2 = obj.param1; % Warning on param2
end
end
Similar code for the set.param2.
Code works fine and I cannot see any better way to do it. The problem - it produces warning "a set method..." like mentioned in title. I suppressed them for the lack of better solution.
Is there a better way to achieve this functionality and without warnings? Obviously not a hacky "solution" like a hidden function SetParam2:
function SetParam2(obj, input)
obj.param2 = input;
end
which confuses editor just enough it doesn't complain.
You could use two layers of properties
one layer which is exposed and Dependent
one layer which is private and actually stores the values
The similar technique is used here in the documentation: Avoid Property Initialization Order Dependency.
classdef TestClass < handle
properties (Access = private)
privateParam1;
privateParam2;
end
properties (Dependent)
param1;
param2;
end
methods
function p1 = get.param1(obj)
p1 = obj.privateParam1;
end
function p2 = get.param2(obj)
p2 = obj.privateParam2;
end
function set.param1(obj, input)
obj.privateParam1 = input;
if (isempty(obj.privateParam2) || obj.privateParam2 < obj.privateParam1)
obj.privateParam2 = obj.param1;
end
end
function set.param2(obj, input)
if (~isempty(obj.privateParam1) && obj.privateParam1 > input)
obj.privateParam2 = obj.privateParam1;
else
obj.privateParam2 = input;
end
end
end
end
The trick here: privateParam1 and privateParam2 stores the two values. The get and set only implemented for the exposed properties param1 and param2: the get returns simply the inner property and in the set both of them can be used without the analyzer warning as they are marked as Dependent.

Matlab - Constructor doesn't initliaize member values

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.

object oriented MATLAB: static method from parent can't set protected property from child

Ok, so I have a parent class MOM with a bunch of properties with the SetAccess attribute set to protected. It has a special static method setProperty for setting its properties:
classdef MOM < handle
properties (SetAccess = 'protected')
age;
occupation;
num_kids;
MOMmusthaves ={'age','occupation','num_kids'};
end
methods
function obj = MOM(varargin)
if iscell(varargin{1,1})
varargin =varargin{1,1};
end
inputstrings=varargin(cellfun(#isstring,varargin)); % get strings out of the inputs
if(isempty(setxor(intersect(inputstrings,obj.MOMmusthaves),obj.MOMmusthaves)))
% if all proper inputs are entered, initialize your object
for pp =1:length(obj.MOMmusthaves)
obj.setProperty(obj,varargin,obj.MOMmusthaves{pp});%find each input in the vararagins, and set it
end
else
display('Hey! These inputs are wrong. type help MOM for an example. Make sure you inlcude inputs for all of the following:'); obj.MOMmusthaves
return;
end
end
end
methods (Static)
function setProperty(obj,varargs,xx)
eval(sprintf('obj.%s = varargs{find(strcmp(''%s'',varargs))+1};',xx,xx));
end
end
end
Then I have a child object KID, which has a couple more properties, also SetAccess protected. When I try to use MOM's static method to set a KID property inside the KID's constructor I get an error :(
The error says:
You cannot set the read-only property 'allowance' of KID.
Basically, it seems like KID doesn't think that it can use MOM's static method as its own (so didn't inherit it properly).
MY QUESTION IS:
Is there any way I can make the static method be recycled and usable to KID for its own protected properties?
JUST FYI, here's something like the KID code;
classdef KID < MOM
properties (SetAccess = 'protected')
gender;
allowance;
favoritecandy;
KIDmusthaves ={'gender','allowance','favoritecandy'};
end
methods
function obj = KID(varargin)
obj = obj#MOM(varargin(:)); % Special construct for instantiating the superclass
inputstrings=varargin(cellfun(#isstring,varargin)); % get strings out of the inputs.
if(isempty(setxor(intersect(inputstrings,obj.KIDmusthaves),obj.KIDmusthaves)))
% if all proper inputs are entered, initialize your object
for pp =1:length(obj.KIDmusthaves)
%find each input in the vararagins, and set it
obj.setProperty(obj,varargin,obj.KIDmusthaves{pp});
end
else
display('please use correct input format. Make sure you include inputs for all of the following:');
obj.KIDmusthaves
return;
end
end
end
end
I'm not really sure what the exact source of the error is; although, I think it may be due to the mutation of the handle object being hidden by the eval.
Regardless, if I understand the intended usage of setProperty, I think it may be easiest to write the function in a non-static form using dot notation (similar to dynamic field names with structs):
methods
function [] = setProperty(obj,musthaves,varargin)
keys = varargin(1:2:end);
values = varargin(2:2:end);
for pp =1:length(keys)
key = keys{k};
if any(strcmp(musthaves,key))
obj.(key) = values{pp};
end
end
end
end
where musthaves is any cell array of property strings
You could also have musthaves be a string that indicates the obj property holding the property list:
methods
function [] = setProperty(obj,musthaves,varargin)
keys = varargin(1:2:end);
values = varargin(2:2:end);
for pp =1:length(keys)
key = keys{k};
if any(strcmp(obj.(musthaves),key))
obj.(key) = values{pp};
end
end
end
end

Sub-struct with dependent fields

In Matlab, I would like a data structure that looks like so:
DataStruct
.model
.Q
.Qchol
.
.
.system
.
.
The structure may well be a class, although I don't really need all the other functionality that goes with oop.
But I require
If Q is assigned something, then automatically Qchol = cholcov(Q).
If Qchol is assigned something, then automatically Q = Qchol' * Qchol.
Meanwhile, both Q and Qchol are stored for fast read-access
And Q and Qchol are writable through simple assignment, e.g.: DS1.mod.Q = value
I know I can make model a class, and have set/get methods for Q and Qchol. However, this really seems like an overkill for just two matrices (plus maybe some more fields). Also Matlab warns me that I should not access other properties during in a set method.
So: What is the best way to have such data structures, preferably without warnings?
You basically want assignment (DS1.mod.Q = value) to have side-effects, which inevitably implies a setter, and hence a class. You should either drop this requirement, or write a class.
If you wish to avoid definition of properties in the class declaration, you could use Dynamic Properties, which allows you to add properties at runtime (although with some telltale syntax addprop()).
EDIT
Patric, the problem goes deeper then just M-lint. Consider the following class:
classdef cantInstantiateMe < handle
properties
x
minus_x
end
methods
function obj = cantInstantiateMe(x)
obj.x = x; % <-- this calls set.x(), which calls set.minus_x(), which calls set.x(), ...
obj.minus_x = -x;
end
function set.x(obj, value)
obj.x = value;
obj.minus_x = -value; % <-- this gives an M-Lint warning
end
function set.minus_x(obj, value)
obj.minus_x = value;
obj.x = -value;
end
end
end
This class cannot be instantiated, because each setter calls the other setter (this is not Matlab-specific). Trying to instantiate on my machine gives:
??? Maximum recursion limit of 500 reached. Use set(0,'RecursionLimit',N)
to change the limit. Be aware that exceeding your available stack space can
crash MATLAB and/or your computer.
At this point I think you have two options:
Make either Q or Qchol a dependent property. This will come at the cost of re-calculating the dependent property each time you read-access it.
Use some private shadow properties e.g. shadow_Q and shadow_Qchol which will be set when the setter for the public property is called, and returned when their getter is called. Similar to:
function set.x(obj, value)
obj.shadow_x = value;
obj.shadow_minus_x = -value;
end
function value = get.x(obj)
value = obj.shadow_x;
end
Note the I did not test this properly, so I don't know all implications in Matlab. In other languages I'm familiar with, this should work fine.
Regarding the warning - my approach is that it is safe to disable the warning, as long as you really know what you are doing.
As suggested by #bavaza, one way to implement this is to use a dependent property with corresponding shadow private properties.
Below is the code implementing the inner data structure (inspired by this post). You need to use composition to make an instance of this class a property of the outer object:
classdef Model < handle
properties (Dependent)
Q
Qchol
end
properties (Access = private)
Q_
Qchol_
end
methods
function obj = Model()
end
function val = get.Q(obj)
val = obj.Q_;
end
function val = get.Qchol(obj)
val = obj.Qchol_;
end
function set.Q(obj, val)
obj.Q_ = val;
obj.Qchol_ = cholcov(val);
end
function set.Qchol(obj, val)
obj.Qchol_ = val;
obj.Q_ = val'*val;
end
end
end
Setting one value using the exposed dependent properties affects both underlying variables:
>> m = Model
m =
Model with properties:
Q: []
Qchol: []
>> m.Qchol = rand(3)
m =
Model with properties:
Q: [3x3 double]
Qchol: [3x3 double]