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]
Related
In MATLAB there are two ways to initialize its properties. Either directly in the properties:
classdef A
properties
foo = 'bar';
end
end
or by explicitly defining a constructor:
classdef B
properties
foo;
end
methods this = B()
this.foo = 'bar';
end
end
Which one is the more preferable way?
(I am asking because there is a similar case in C++ where the preferred way is to initialize the member variables with a colon after the constructor rather than assigning variables within the constructor).
In most cases, the two methods behave the same, and the choice is just a preference depending on which you find clearer/easier to maintain etc.
But they are not the same, and there are cases where you will get yourself in trouble if you aren't aware of the differences.
The essential difference is that properties that are initialised in the constructor are initialised separately each time an object is constructed, whereas properties that are initialised in the properties block with a default value are initialised once, when the class definition is first read. The default value in a properties block is the default value of the class, not of the object; and (using reflection) you can query that default value even if no instance of the class has yet been instantiated.
In most cases, this makes no difference - but when the initial value is a handle object, or the output of a non-determinate function it does. So consider the following two classes:
classdef A
properties
foo
end
methods
function obj = A
obj.foo = containers.Map;
end
end
end
classdef B
properties
foo = containers.Map
end
end
Note that containers.Map is a handle class.
In class A, every time you create a new instance of A you get a new/different containers.Map for its foo. In B, every instance of B gets the same containers.Map for its foo, as the property is initialised only once, the first time the class definition is read. So if you modify foo for any object of class B, that change is propagated to all other instances of class B, as you can see:
>> a1 = A; a2 = A; a1.foo('greeting') = 'hello'; a2.foo('greeting') = 'bonjour';
>> a1.foo('greeting'), a2.foo('greeting')
ans =
'hello'
ans =
'bonjour'
>> b1 = B; b2 = B; b1.foo('greeting') = 'hello'; b2.foo('greeting') = 'bonjour';
>> b1.foo('greeting'), b2.foo('greeting')
ans =
'bonjour'
ans =
'bonjour'
>> % Note that b1.foo has changed as a result of setting b2.foo
This point about handle classes as default values often trips people up; but the behaviour is not specific to handle classes. For example, consider the following variation:
classdef A
properties
foo
end
methods
function obj = A
obj.foo = datetime('now');
end
end
end
classdef B
properties
foo = datetime('now')
end
end
Here A will store the creation time of each object, whereas B will store the time at which the class was first initialised, for all objects, no matter when they were created.
In case you find this behaviour confusing, see https://undocumentedmatlab.com/blog/handle-object-as-default-class-property-value, and particularly the comment thread underneath that article, for a discussion of the issue, and an explanation for the reasons MATLAB is designed in this way.
Edit: Great follow up question in the comments, regarding the behaviour of clear and its relation to this issue.
Using the second implementation of the classes above (with datetime), look at the following:
>> a = A; b = B; datestr(a.foo), datestr(b.foo)
ans =
'01-Sep-2018 18:59:30'
ans =
'01-Sep-2018 18:59:30'
>> clear variables
>> a = A; b = B; datestr(a.foo), datestr(b.foo)
ans =
'01-Sep-2018 18:59:48'
ans =
'01-Sep-2018 18:59:30'
>> clear classes
>> a = A; b = B; datestr(a.foo), datestr(b.foo)
ans =
'01-Sep-2018 18:59:57'
ans =
'01-Sep-2018 18:59:57'
So we first of all create an A and a B, and display their foos, and they both show the same time. Then we wait a little while, do clear variables, and we do it again. Note that the foo from A is the new time, and the foo from B is still the same as before. Finally we wait a little more time, we do clear classes, and we do it again. This time both A and B have the new time.
Why? Because clear variables merely removes references to the variables from the workspace. The class definition of B is not cleared, so when we create another B, it still uses the value from when the class definition was first read. clear classes, by contrast, also removes the class definition, so when we later construct a new B, it gets that time, as the class definition is then reread. All this is irrelevant to A, as foo is just given a value at construction time.
Note that clear classes clears all class definitions: you can clear the definition of only class B using clear B.
It is on your choice except for some cases.
Let me mention when we use the colon in Constructor function inC++:
1- Calling base class constructors
2- Initializing member variables before the body of the constructor executes.
No.#1 can be also used in the body but we should use the colon in No.#2 when the member is const.
BUT
But here is Matlab, with its own language syntax and structure.
Use which one do your job.
But here in Matlab when you want to define Constant properties you MUST define it in properties part and you can't do it in initializer/constructor function.
classdef NamedConst
properties (Constant)
R = pi/180; % Can't define it in constructor body, because it is `Constant properties`
end
%class body
end
Is there a way to define static member variables in MATLAB classes?
This doesn't work:
classdef A
properties ( Static )
m = 0;
end
end
It suggests to use keyword "Constant" instead of "Static", the constant properties cannot be modified. I want a variable common to all objects of class A and I want to be able to modify that variable in methods of class A.
So what I need is a private static member variable. Is there a way to obtain it in MATLAB?
Found out that a workaround can be done using persistent variables in static member functions.
In this case you should inherit all your classes from a base class like the following.
classdef object < handle
properties ( GetAccess = 'public', SetAccess = 'private' )
id
end
methods ( Access = 'protected' )
function obj = object()
obj.id = object.increment();
end
end
methods ( Static, Access = 'private' )
function result = increment()
persistent stamp;
if isempty( stamp )
stamp = 0;
end
stamp = stamp + uint32(1);
result = stamp;
end
end
end
You can not, it is by design. You should use a persistent variable (technique from the MATLAB as 1980 applied in year 2011)!
For completeness I should mention that actually there is as of 2010b an undocumented and probably not longer supported static property modifier.
For background see here the answer of Dave Foti, MATLAB OO group manager:
In MATLAB, classes can define Constant
properties, but not "static"
properties in the sense of other
languages like C++. There were beta
releases that experimented with
"Static" properties and the
undocumented attribute remains from
then. However, the Static attribute is
undocumented, should not be used, and
will likely be removed in a future
MATLAB release. R2008a implements it
as a synonym for Constant and provides
no additional functionality beyond
the documented behavior of Constant
properties.
Constant properties may not be changed
from the initial value specified in
the property declaration. There are a
couple of reasons why MATLAB works
the way it does. First, MATLAB has
longstanding rules that variables
always take precedent over the names
of functions and classes and that
assignment statements introduce a
variable if one doesn't already exist.
Thus, any expression of the form "A.B
= C" will introduce a new variable A that is a struct array containing a
field B whose value is C. If "A.B = C"
could refer to a static property of
class A, then class A would take
precedent over variable A and this
would be a very significant
incompatibility with prior releases
of MATLAB. It would mean that an
m-file containing the assignment
statement "A.B = C" could have its
meaning changed by the introduction
of a class named A somewhere on the
MATLAB path. MATLAB programmers have
always been able to rely on assignment
statements introducing variables that
shadow any other use of the same name.
Second, we have observed that static
data is rarely used in other classes
except as private data within the
class or as public constants. For
example, a survey of several Java
class libraries found that all public
static fields were also final. In
MATLAB, Constant properties can be
used like "public final static"
fields in Java. For data internal to a
class, MATLAB already has persistent
variables that can be created inside
of private or protected methods or
local functions privately used by a
class. There are also good reasons to
avoid static data in MATLAB where
possible. If a class has static data,
it can be difficult to use the same
class in multiple applications
because the static data can be a
source of conflicts among
applications. In some other languages,
this is less of an issue because
different applications are separately
compiled into executables running in
different processes with different
copies of class static data. In
MATLAB, frequently many different
applications may be running in the
same process and environment with a
single copy of each class.
Here's a direct way to create a static property in Matlab. The only difference between this implementation and a hypothetical (but impossible; see Mikhail's answer) true static property is the syntax for setting the member variable.
classdef StaticVarClass
methods (Static = true)
function val = staticVar(newval)
persistent currentval;
if nargin >= 1
currentval = newval;
end
val = currentval;
end
end
end
Now the static property staticVar can be read via:
StaticVarClass.staticVar
...and be set via:
StaticVarClass.staticVar(newval);
So, for instance, this is the expected output from a test of this functionality:
>> StaticVarClass.staticVar
ans =
[]
>> StaticVarClass.staticVar('foobar')
ans =
foobar
>> StaticVarClass.staticVar
ans =
foobar
>>
This approach works just as well for private static properties like you requested, but the demo code is a little longer. Note that this is not a handle class (though it would work perfectly well on a handle class as well).
classdef StaticVarClass
methods (Access = private, Static = true)
function val = staticVar(newval)
persistent currentval;
if nargin >= 1
currentval = newval;
end
val = currentval;
end
end
methods
function this = setStatic(this, newval)
StaticVarClass.staticVar(newval);
end
function v = getStatic(this)
v = StaticVarClass.staticVar;
end
end
end
...and the test:
>> x = StaticVarClass
x =
StaticVarClass with no properties.
Methods
>> x.getStatic
ans =
[]
>> x.setStatic('foobar')
ans =
StaticVarClass with no properties.
Methods
>> x.getStatic
ans =
foobar
>>
(just to inform)
there is (another?) way to create static-like data in matlab
suppose that you have a "handle" class which its name is "car"
if you want the car class to have static data, you could construct another handle class and use it in car class throw composition, the latter class works as a static data for car class
classdef car<handle
properties
static_data:STATIC_DATA_HOLDER;
end
end
classdef STATIC_DATA_HOLDER<handle
properties
data
end
end
this way when you create first instance of a car class, an instance of STATIC_DATA_HOLDER will be created and when you create second instance of car class it uses previously created STATIC_DATA_HOLDER class.
these code tested with "MATLAB 2013b"
Another workaround to get something like static properties is to use the fact that initialisation code for member variables is only executed once when the class file is loaded. That means, if you have a definition like
classdef foo
properties
stuff = some_function()
end
end
then some_function is invoked only once, and if it returns an object of class type, this will be shared by all instances. I've added a sample implementation that shows how that can be used:
classdef ClassWithStaticMembers
properties
classvars = StaticVarContainer('foo', 0, 'bar', 2);
othervar
end
methods
function obj=ClassWithStaticMembers(var)
obj.othervar = var;
end
end
end
classdef StaticVarContainer < dynamicprops
methods
function obj=StaticVarContainer(varargin)
for i=1:2:numel(varargin)
obj.addprop(varargin{i});
obj.(varargin{i}) = varargin{i+1};
end
end
end
end
If you run this sample code
obj1 = ClassWithStaticMembers(3);
obj2 = ClassWithStaticMembers(5);
obj1.classvars.foo = [2,3];
obj1.othervar
obj1.classvars
obj2.othervar
obj2.classvars
you'll see, that classvars is indeed shared. I think this solution is much nicer than using persistent variables in functions, since you can reuse the StaticVarContainer as often as you want, it's easier to use, and furthermore, you directly see the initialisation of the static variables in the properties section.
To get the result, that is desired in the OP's question (i.e. implementing an object counter) the shared property can be made Constant, so that it can be referenced without an instance at hand:
classdef ClassWithCounter
properties (Constant)
static = StaticVarContainer('counter', 0);
end
methods
function obj=ClassWithCounter()
obj.static.counter = obj.static.counter + 1;
end
end
end
clear all
obj1 = ClassWithCounter();
obj2 = ClassWithCounter();
obj3 = ClassWithCounter();
ClassWithCounter.static.counter
Note, that the Constant attribute only means that, e.g. obj1.static cannot be changed, but it does not affect obj1.static.counter which is not constant, and can be set to heart's desire.
I come from a Java background. I am having issues with classes in Matlab particularly getters and setters. getting a message saying conflict between handle and value class I'm a little lost with what to do so any help for lack of a better word will be helpful.
classdef Person
properties(Access = private)
name;
age;
end
methods
% class constructor
function obj = Person(age,name)
obj.age = age;
obj.name = name;
end
%getters
function name = get.name(obj)
end
function age = get.age(obj)
end
%setters
function value = set.name(obj,name)
end
function value = set.age(obj,age)
end
end
end
Implementation
Since your class is currently a subclass of the default Value class, your setters need to return the modified object:
function obj = set.name(obj,name)
end
function obj = set.age(obj,age)
end
From the documention: "If you pass [a value class] to a function, the function must return the modified object." And in particular: "In value classes, methods ... that modify the object must return a modified object to copy over the existing object variable".
Handle classes (classdef Person < handle) do not need to return the modified object (like returning void):
function [] = set.name(obj,name)
end
function [] = set.age(obj,age)
end
Value vs. Handle
Going a bit deeper, the difference between a Value class and a Handle class lies mostly in assignment:
Assigning a Value class instance to a variable creates a copy of that class.
Assigning a Handle class instance to a variable create a reference (alias) to that instance.
The Mathworks has a good rundown on this topic.
To paraphrase their illustration, the behavior of a Value class is
% p is an instance of Polynomial
p = Polynomial();
% p2 is also an instance of Polynomial with p's state at assignment
p2 = p;
and of a Handle class is
% db is an instance of Database
db = Database();
% db2 is a reference to the db instance
db2 = db;
Quick'n Dirty from the Java perspective:
- "handle" classes are what your mind is set to. proper object instances with pointers to them. use them.
- "value" classes are always returning a full clone of whatever object (which has been modified by what you just did, e.g. setting a name).
the reason they have both in Matlab is that in Matlab you would expect the "value" behaviour natively. Imagine you have a matrix A = [1 2; 3 4], then assign that via B = A. if you now set B(1) = -1 you'd hope that A(1) is still 1, right? this is because matlab keeps track of "copies" and truly creates them as you modify different variables initially set to the same matrix. in OOP you'd have A(1)=-1 now as everythings an object reference.
furthermore, "native" matlab routines dont have a "this/self/me" variable that contains the instance reference to access from within functions. instead, the convention is that the class instance will be prepended to the function's argument list.
so for a function call myclass.mymethod(arg1,arg1), the declaration must be
function mymethod(this, arg1, arg2)
% Note that the name you choose for "this" is arbitrary!
end
mind you, this is the java-perspective (and also my favourite one), the above function call is equivalent to mymethod(myclass,arg1,arg1). this is more native to matlab-style, but somehow makes it harder to see you're calling an objects method.
now, regarding setters/getters: for handle classes, everything feels java-ish now:
classdef MyClass < handle
properties
MyProp;
end
methods
function set.MyProp(this, value) %Note: setMyProp is also valid!
... % do checks etc, trigger calls,
this.MyProp = value;
end
function value = get.MyProp(this)
... % notify, update, triggers etc
value = this.MyProp;
end
end
Of course it goes without saying that you dont need to define a getter if you just want to return the value, i.e. myclassinstance.MyProp will work without any just as well.
Finally, getters/setters for value classes are something that [never encountered me/i never needed] in my 7 years of matlab oop, so my advise would be to go with handle classes and enjoy happy matlab coding :-)
otherwise, the above explanation & official matlab docs is doing the job for value class getter/setters.
Writing a subclass of dynamicprops allows to me to add properties dynamically to an object:
addprop(obj, 'new_prop')
This is great, but I would also love to create set / get functions for these properties on the fly. Or analysis functions that work on these dynamic properties.
My experience with Matlab has been so far, that once I create an instance of a class, adding new methods is not possible. That is very cumbersome, because my object may contain a lot of data, which I'll have to re-load every time that I want to add a new method (because I have to do clear classes).
So is there a way to add methods on the fly?
You cannot add methods like you add dynamic properties. However, there are two ways for implementing new methods during development that won't require you to re-load the data every time.
(1) I write standard methods as separate functions, and call them as myMethod(obj) during development. Once I'm sure they're stable, I add their signature into the class definition file - this requires a clear classes, of course, but it is a much delayed one, and from time to time you may have to shut down Matlab, anyway.
(2) With set/get methods, things are a little trickier. If you are using dynamicprops to add new properties, you can also specify their set/get methods, however (most likely, these methods/functions will want to receive the name of the property so that they know what to refer to):
addprop(obj,'new_prop');
prop = findprop(obj,'new_prop');
prop.SetMethod = #(obj,val)yourCustomSetMethod(obj,val,'new_prop')
EDIT
(2.1) Here's an example of how to set up a hidden property to store and retrieve results (based on jmlopez' answer). Obviously this can be improved a lot if you have a better idea what you're actually designing
classdef myDynamicClass < dynamicprops
properties (Hidden)
name %# class name
store %# structure that stores the values of the dynamic properties
end
methods
function self = myDynamicClass(clsname, varargin)
% self = myDynamicClass(clsname, propname, type)
% here type is a handle to a basic datatype.
self.name_ = clsname;
for i=1:2:length(varargin)
key = varargin{i};
addprop(self, key);
prop = findprop(self, key);
prop.SetMethod = #(obj,val)myDynamicClass.setMethod(obj,val,key);
prop.GetMethod = #(obj)myDynamicClass.getMethod(obj,key);
end
end
function out = classname(self)
out = self.name_;
end
end
methods (Static, Hidden) %# you may want to put these in a separate fcn instead
function setMethod(self,val,key)
%# have a generic test, for example, force nonempty double
validateattributes(val,{'double'},{'nonempty'}); %# will error if not double or if empty
%# store
self.store.(key) = val;
end
function val = getMethod(self,key)
%# check whether the property exists already, return NaN otherwise
%# could also use this to load from file if the data is not supposed to be loaded on construction
if isfield(self.store,key)
val = self.store.(key);
else
val = NaN;
end
end
end
end
I'm adding this answer because I think that this is not intuitive. At least not to myself at this moment. After finding this question I thought I had what I needed to be able to define the set/get methods for my dynamic class. All I wanted to achieve with this was something similar to what python does with its __setattr__ method. In any case, here is a continuation of the class made by #jonas a while ago with a few modifications to add the our custom set method.
classdef myDynamicClass < dynamicprops
properties (Hidden)
name_ %# class name
end
methods
function self = myDynamicClass(clsname, varargin)
% self = myDynamicClass(clsname, propname, type)
% here type is a handle to a basic datatype.
self.name_ = clsname;
for i=1:2:length(varargin)
key = varargin{i};
addprop(self, key);
prop = findprop(self, key);
prop.SetMethod = makefunc(key, varargin{i+1});
end
end
function out = classname(self)
out = self.name_;
end
end
end
function h = makefunc(key, argtype)
h = #newfunc;
function newfunc(obj, val)
obj.(key) = argtype(val);
end
end
With this class I'm defining the set method so that the parameter passed to the attribute is copied to the right type. To see what I mean consider the following usage:
>> p_int = myDynamicClass('Point', 'x', #int8, 'y', #int32);
>> p_int.x = 1000
p_int =
myDynamicClass with properties:
y: []
x: 127
>> class(p_int.x)
ans =
int8
With this we have forced the x attribute to be an integer of 8 bits which can only hold integers from -128 to 127. Also notice how the class of each attribute gives us the intended type.
My experience with Matlab has been so far, that once I create an instance of a class, adding new methods is not possible. That is very cumbersome, because my object may contain a lot of data, which I'll have to re-load everytime that I want to add a new method (because I have to do clear classes).
It's worth noting for present-day readers of this question that this is no longer true. As of MATLAB R2014b MATLAB updates class definitions at the moment you save them, and the behaviour of existing class instances automatically updates accordingly. In the case of adding new methods, this is uncomplicated: the new method simply becomes available to call on class instances even if they were created before the method was added to the class.
The solutions given for choosing set/get methods for dynamic properties still apply.
There are still cases where you might want to add methods to an instance dynamically and the method doesn't constitute a property set/get method. I think the only answer in this case is to assign a function handle as the value to a dynamic property. This doesn't create a bona fide method, but will allow you to call it in the same way you would a method call:
addprop(obj, 'new_method');
obj.new_method = #(varargin) my_method(obj,varargin{:});
Calls to obj.new_method(args) are thus passed to my_method; however this only works with a scalar obj; an array of instances will have separate values for the new_method property so obj.new_method no longer resolves to a single function handle that can be called if obj is an array.
Is there a way to define static member variables in MATLAB classes?
This doesn't work:
classdef A
properties ( Static )
m = 0;
end
end
It suggests to use keyword "Constant" instead of "Static", the constant properties cannot be modified. I want a variable common to all objects of class A and I want to be able to modify that variable in methods of class A.
So what I need is a private static member variable. Is there a way to obtain it in MATLAB?
Found out that a workaround can be done using persistent variables in static member functions.
In this case you should inherit all your classes from a base class like the following.
classdef object < handle
properties ( GetAccess = 'public', SetAccess = 'private' )
id
end
methods ( Access = 'protected' )
function obj = object()
obj.id = object.increment();
end
end
methods ( Static, Access = 'private' )
function result = increment()
persistent stamp;
if isempty( stamp )
stamp = 0;
end
stamp = stamp + uint32(1);
result = stamp;
end
end
end
You can not, it is by design. You should use a persistent variable (technique from the MATLAB as 1980 applied in year 2011)!
For completeness I should mention that actually there is as of 2010b an undocumented and probably not longer supported static property modifier.
For background see here the answer of Dave Foti, MATLAB OO group manager:
In MATLAB, classes can define Constant
properties, but not "static"
properties in the sense of other
languages like C++. There were beta
releases that experimented with
"Static" properties and the
undocumented attribute remains from
then. However, the Static attribute is
undocumented, should not be used, and
will likely be removed in a future
MATLAB release. R2008a implements it
as a synonym for Constant and provides
no additional functionality beyond
the documented behavior of Constant
properties.
Constant properties may not be changed
from the initial value specified in
the property declaration. There are a
couple of reasons why MATLAB works
the way it does. First, MATLAB has
longstanding rules that variables
always take precedent over the names
of functions and classes and that
assignment statements introduce a
variable if one doesn't already exist.
Thus, any expression of the form "A.B
= C" will introduce a new variable A that is a struct array containing a
field B whose value is C. If "A.B = C"
could refer to a static property of
class A, then class A would take
precedent over variable A and this
would be a very significant
incompatibility with prior releases
of MATLAB. It would mean that an
m-file containing the assignment
statement "A.B = C" could have its
meaning changed by the introduction
of a class named A somewhere on the
MATLAB path. MATLAB programmers have
always been able to rely on assignment
statements introducing variables that
shadow any other use of the same name.
Second, we have observed that static
data is rarely used in other classes
except as private data within the
class or as public constants. For
example, a survey of several Java
class libraries found that all public
static fields were also final. In
MATLAB, Constant properties can be
used like "public final static"
fields in Java. For data internal to a
class, MATLAB already has persistent
variables that can be created inside
of private or protected methods or
local functions privately used by a
class. There are also good reasons to
avoid static data in MATLAB where
possible. If a class has static data,
it can be difficult to use the same
class in multiple applications
because the static data can be a
source of conflicts among
applications. In some other languages,
this is less of an issue because
different applications are separately
compiled into executables running in
different processes with different
copies of class static data. In
MATLAB, frequently many different
applications may be running in the
same process and environment with a
single copy of each class.
Here's a direct way to create a static property in Matlab. The only difference between this implementation and a hypothetical (but impossible; see Mikhail's answer) true static property is the syntax for setting the member variable.
classdef StaticVarClass
methods (Static = true)
function val = staticVar(newval)
persistent currentval;
if nargin >= 1
currentval = newval;
end
val = currentval;
end
end
end
Now the static property staticVar can be read via:
StaticVarClass.staticVar
...and be set via:
StaticVarClass.staticVar(newval);
So, for instance, this is the expected output from a test of this functionality:
>> StaticVarClass.staticVar
ans =
[]
>> StaticVarClass.staticVar('foobar')
ans =
foobar
>> StaticVarClass.staticVar
ans =
foobar
>>
This approach works just as well for private static properties like you requested, but the demo code is a little longer. Note that this is not a handle class (though it would work perfectly well on a handle class as well).
classdef StaticVarClass
methods (Access = private, Static = true)
function val = staticVar(newval)
persistent currentval;
if nargin >= 1
currentval = newval;
end
val = currentval;
end
end
methods
function this = setStatic(this, newval)
StaticVarClass.staticVar(newval);
end
function v = getStatic(this)
v = StaticVarClass.staticVar;
end
end
end
...and the test:
>> x = StaticVarClass
x =
StaticVarClass with no properties.
Methods
>> x.getStatic
ans =
[]
>> x.setStatic('foobar')
ans =
StaticVarClass with no properties.
Methods
>> x.getStatic
ans =
foobar
>>
(just to inform)
there is (another?) way to create static-like data in matlab
suppose that you have a "handle" class which its name is "car"
if you want the car class to have static data, you could construct another handle class and use it in car class throw composition, the latter class works as a static data for car class
classdef car<handle
properties
static_data:STATIC_DATA_HOLDER;
end
end
classdef STATIC_DATA_HOLDER<handle
properties
data
end
end
this way when you create first instance of a car class, an instance of STATIC_DATA_HOLDER will be created and when you create second instance of car class it uses previously created STATIC_DATA_HOLDER class.
these code tested with "MATLAB 2013b"
Another workaround to get something like static properties is to use the fact that initialisation code for member variables is only executed once when the class file is loaded. That means, if you have a definition like
classdef foo
properties
stuff = some_function()
end
end
then some_function is invoked only once, and if it returns an object of class type, this will be shared by all instances. I've added a sample implementation that shows how that can be used:
classdef ClassWithStaticMembers
properties
classvars = StaticVarContainer('foo', 0, 'bar', 2);
othervar
end
methods
function obj=ClassWithStaticMembers(var)
obj.othervar = var;
end
end
end
classdef StaticVarContainer < dynamicprops
methods
function obj=StaticVarContainer(varargin)
for i=1:2:numel(varargin)
obj.addprop(varargin{i});
obj.(varargin{i}) = varargin{i+1};
end
end
end
end
If you run this sample code
obj1 = ClassWithStaticMembers(3);
obj2 = ClassWithStaticMembers(5);
obj1.classvars.foo = [2,3];
obj1.othervar
obj1.classvars
obj2.othervar
obj2.classvars
you'll see, that classvars is indeed shared. I think this solution is much nicer than using persistent variables in functions, since you can reuse the StaticVarContainer as often as you want, it's easier to use, and furthermore, you directly see the initialisation of the static variables in the properties section.
To get the result, that is desired in the OP's question (i.e. implementing an object counter) the shared property can be made Constant, so that it can be referenced without an instance at hand:
classdef ClassWithCounter
properties (Constant)
static = StaticVarContainer('counter', 0);
end
methods
function obj=ClassWithCounter()
obj.static.counter = obj.static.counter + 1;
end
end
end
clear all
obj1 = ClassWithCounter();
obj2 = ClassWithCounter();
obj3 = ClassWithCounter();
ClassWithCounter.static.counter
Note, that the Constant attribute only means that, e.g. obj1.static cannot be changed, but it does not affect obj1.static.counter which is not constant, and can be set to heart's desire.