create enum with MATLAB [duplicate] - matlab

Are there enumerated types in MATLAB? If not, what are the alternatives?

Starting from R2010b, MATLAB supports enumerations.
Example from the documentation:
classdef Colors
properties
R = 0;
G = 0;
B = 0;
end
methods
function c = Colors(r, g, b)
c.R = r; c.G = g; c.B = b;
end
end
enumeration
Red (1, 0, 0)
Green (0, 1, 0)
Blue (0, 0, 1)
end
end

You can get some of the functionality with new-style MATLAB classes:
classdef (Sealed) Colors
properties (Constant)
RED = 1;
GREEN = 2;
BLUE = 3;
end
methods (Access = private) % private so that you cant instantiate
function out = Colors
end
end
end
This isn't really a type, but since MATLAB is loosely typed, if you use integers, you can do things that approximate it:
line1 = Colors.RED;
...
if Colors.BLUE == line1
end
In this case, MATLAB "enums" are close to C-style enums - substitute syntax for integers.
With the careful use of static methods, you can even make MATLAB enums approach Ada's in sophistication, but unfortunately with clumsier syntax.

If you want to do something similar to what Marc suggested, you could simply make a structure to represent your enumerated types instead of a whole new class:
colors = struct('RED', 1, 'GREEN', 2, 'BLUE', 3);
One benefit is that you can easily access structures in two different ways. You can specify a field directly using the field name:
a = colors.RED;
or you can use dynamic field names if you have the field name in a string:
a = colors.('RED');
In truth, there are a few benefits to doing what Marc suggested and creating a whole new class to represent an "enum" object:
You can control how the object is modified.
You can keep the definition in one place and easily use it in multiple places.
You can control failures and make them more "graceful", like returning an empty matrix if you try to access a non-existent field (as opposed to throwing an error).
However, if you don't need that sort of complexity and just need to do something quick, a structure is likely the easiest and most straight-forward implementation. It will also work with older versions of MATLAB that don't use the newest OOP framework.

There is actually a keyword in MATLAB R2009b called 'enumeration'. It seems to be undocumented, and I cannot say I know how to use it, but the functionality is probably there.
You can find it in matlabroot\toolbox\distcomp\examples\+examples
classdef(Enumeration) DmatFileMode < int32
enumeration
ReadMode(0)
ReadCompatibilityMode(1)
WriteMode(2)
end
<snip>
end

You could also use Java enum classes from your Matlab code. Define them in Java and put them on your Matlab's javaclasspath.
// Java class definition
package test;
public enum ColorEnum {
RED, GREEN, BLUE
}
You can reference them by name in M-code.
mycolor = test.ColorEnum.RED
if mycolor == test.ColorEnum.RED
disp('got red');
else
disp('got other color');
end
% Use ordinal() to get a primitive you can use in a switch statement
switch mycolor.ordinal
case test.ColorEnum.BLUE.ordinal
disp('blue');
otherwise
disp(sprintf('other color: %s', char(mycolor.toString())))
end
It won't catch comparisons to other types, though. And comparison to string has an odd return size.
>> test.ColorEnum.RED == 'GREEN'
ans =
0
>> test.ColorEnum.RED == 'RED'
ans =
1 1 1

You could make a Matlab class that behaves like a Java's old typesafe enum pattern. A modification of Marc's solution could take it from C-style typedefs to more like Java-style typesafe enums. In this version, the values in the constants are typed Color objects.
The upsides:
The type can be checked (at runtime) by == and other operations to prevent accidental comparison to raw numerics or other types of enums.
You can explicitly check the type of your variables (at runtime).
Values are displayed with readable names instead of the opaque codes.
Operations like mean() and std() that don't make sense on enums are disallowed.
Downsides:
Longer class definition. But, this is all boilerplate, and can be reused for any other enum class, changing just the class name and Constant properties.
These enums cannot be used directly in switch blocks. Need to pop the Code out, which loses some type safety.
Objects will be slower than primitives. Relevant if you're using constants inside loops.
On the whole, I don't know which approach is better. Haven't used either in practice.
classdef (Sealed) Color
%COLOR Example of Java-style typesafe enum for Matlab
properties (Constant)
RED = Color(1, 'RED');
GREEN = Color(2, 'GREEN');
BLUE = Color(3, 'BLUE');
end
properties (SetAccess=private)
% All these properties are immutable.
Code;
Name;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
methods (Access = private)
%private so that you can't instatiate directly
function out = Color(InCode, InName)
out.Code = InCode;
out.Name = InName;
end
end
methods (Static = true)
function needa(obj)
%NEEDA Asserts that obj must be a Color
if ~isa(obj, mfilename)
error('Input must be a %s; got a %s', mfilename, class(obj));
end
end
end
methods (Access = public)
function display(obj)
disp([inputname(1) ' =']);
disp(obj);
end
function disp(obj)
if isscalar(obj)
disp(sprintf('%s: %s (%d)', class(obj), obj.Name, obj.Code));
else
disp(sprintf('%s array: size %s', class(obj), mat2str(size(obj))));
end
end
function out = eq(a, b)
%EQ Basic "type-safe" eq
check_type_safety(a, b);
out = [a.Code] == [b.Code];
end
function [tf,loc] = ismember(a, b)
check_type_safety(a, b);
[tf,loc] = ismember([a.Code], [b.Code]);
end
function check_type_safety(varargin)
%CHECK_TYPE_SAFETY Check that all inputs are of this enum type
for i = 1:nargin
if ~isa(varargin{i}, mfilename)
error('Non-typesafe comparison of %s vs. %s', mfilename, class(varargin{i}));
end
end
end
end
end
Here's a function to exercise it.
function do_stuff_with_color(c)
%DO_STUFF_WITH_COLOR Demo use of the Color typesafe enum
Color.needa(c); % Make sure input was a color
if (c == Color.BLUE)
disp('color was blue');
else
disp('color was not blue');
end
% To work with switch statements, you have to explicitly pop the code out
switch c.Code
case Color.BLUE.Code
disp('blue');
otherwise
disp(sprintf('some other color: %s', c.Name));
end
Example of use:
>> Color.RED == Color.RED
ans =
1
>> Color.RED == 1
??? Error using ==> Color>Color.check_type_safety at 55
Non-typesafe comparison of Color vs. double
Error in ==> Color>Color.eq at 44
check_type_safety(a, b);
>> do_stuff_with_color(Color.BLUE)
color was blue
blue
>> do_stuff_with_color(Color.GREEN)
color was not blue
some other color: GREEN
>> do_stuff_with_color(1+1) % oops - passing the wrong type, should error
??? Error using ==> Color>Color.needa at 26
Input must be a Color; got a double
Error in ==> do_stuff_with_color at 4
Color.needa(c); % Make sure input was a color
>>
A minor quirk in both approaches: the C convention of putting the constant on the left hand of the "==" to prevent bad assignment doesn't help as much here. In Matlab, if you accidentally use "=" with this constant on the LHS, instead of an error, it'll just create a new local struct variable named Colors, and it will mask the enum class.
>> Colors.BLUE = 42
Colors =
BLUE: 42
>> Color.BLUE = 42
Color =
BLUE: 42
>> Color.RED
??? Reference to non-existent field 'RED'.

If you have access to the Statistics Toolbox, you might consider using a categorical object.

After trying out the other suggestions on this page, I landed on Andrew's fully object-oriented approach. Very nice - thanks Andrew.
In case anyone is interested, however, I made (what I think are) some improvements. In particular, I removed the need to double-specify the name of the enum object. The names are now derived using reflection and the metaclass system. Further, the eq() and ismember() functions were re-written to give back properly-shaped return values for matrices of enum objects. And finally, the check_type_safety() function was modified to make it compatible with package directories (e.g. namespaces).
Seems to work nicely, but let me know what you think:
classdef (Sealed) Color
%COLOR Example of Java-style typesafe enum for Matlab
properties (Constant)
RED = Color(1);
GREEN = Color(2);
BLUE = Color(3);
end
methods (Access = private) % private so that you can''t instatiate directly
function out = Color(InCode)
out.Code = InCode;
end
end
% ============================================================================
% Everything from here down is completely boilerplate - no need to change anything.
% ============================================================================
properties (SetAccess=private) % All these properties are immutable.
Code;
end
properties (Dependent, SetAccess=private)
Name;
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
methods
function out = eq(a, b) %EQ Basic "type-safe" eq
check_type_safety(a, b);
out = reshape([a.Code],size(a)) == reshape([b.Code],size(b));
end
function [tf,loc] = ismember(a, b)
check_type_safety(a, b);
[tf,loc] = ismember(reshape([a.Code],size(a)), [b.Code]);
end
function check_type_safety(varargin) %CHECK_TYPE_SAFETY Check that all inputs are of this enum type
theClass = class(varargin{1});
for ii = 2:nargin
if ~isa(varargin{ii}, theClass)
error('Non-typesafe comparison of %s vs. %s', theClass, class(varargin{ii}));
end
end
end
% Display stuff:
function display(obj)
disp([inputname(1) ' =']);
disp(obj);
end
function disp(obj)
if isscalar(obj)
fprintf('%s: %s (%d)\n', class(obj), obj.Name, obj.Code);
else
fprintf('%s array: size %s\n', class(obj), mat2str(size(obj)));
end
end
function name=get.Name(obj)
mc=metaclass(obj);
mp=mc.Properties;
for ii=1:length(mp)
if (mp{ii}.Constant && isequal(obj.(mp{ii}.Name).Code,obj.Code))
name = mp{ii}.Name;
return;
end;
end;
error('Unable to find a %s value of %d',class(obj),obj.Code);
end;
end
end
Thanks,
Mason

Toys = {'Buzz', 'Woody', 'Rex', 'Hamm'};
Toys{3}
ans = 'Rex'

If you need the enumerated types just for passing to C# or .NET assembly,
you can construct and pass the enums with MATLAB 2010:
A = NET.addAssembly(MyName.dll)
% suppose you have enum called "MyAlerts" in your assembly
myvar = MyName.MyAlerts.('value_1');
you can also check the official MathWorks answer at
How do I use .NET enumerated values in MATLAB 7.8 (R2009a)?
// the enum "MyAlerts" in c# will look something like this
public enum MyAlerts
{
value_1 = 0,
value_2 = 1,
MyAlerts_Count = 2,
}

Related

Trouble modifying property in superclass from subclass in matlab

I'm having a weird problem using object oriented matlab, and I'm not sure if I'm completely missing something, or I've hit some unusual behaviour.
I have a superclass defined as follows:
classdef (Abstract) AbstractSimulationData < matlab.mixin.Heterogeneous
properties (Abstract)
name
data
end
properties
timeStamp = -1
end
methods (Abstract)
CalculateData(obj, t)
end
methods
function data = GetData(obj, t)
if obj.timeStamp == t.t
data = obj.data;
else
obj.timeStamp = t.t;
obj.CalculateData(t);
data = obj.data;
end
end
end
end
When the concrete class implements the method CalculateData I intend it to set the superclass property data.
Two concrete classes from this are:
classdef A < AbstractSimulationData
properties
name = 'A'
data = []
end
methods
function obj = A
% No special initialisation
end
function CalculateData(obj, t)
test = t.B.GetData(t)
obj.data = rand(2,10);
end
end
end
And:
classdef B < AbstractSimulationData
properties
name = 'B'
data = containers.Map
end
methods
function obj = B
% No special initialisation
end
function CalculateData(obj, t)
if isempty(obj.data)
obj.data('left') = 1;
obj.data('right') = 2;
end
% Other operations
end
end
end
Within the A.CalculateData method I call the GetData method for B. This in turn calls the B.CalculateData method.
Now, as it filters back up, the data property gets set correctly so that B.GetData returns the value that was set in B.CalculateData.
But, when I go the next step up to A.GetData it returns [], the initialised value. Going through debug mode, the calculations definitely work in A.CalculateData and it seems to set data correctly, but when it jumps back up to the superclass obj.data is the default value from A.
A minimum working example to get this behaviour:
t.B = B();
t.t = 1;
a = A;
a.GetData(t);
>> test =
Map with properties:
Count: 2
KeyType: char
ValueType: any
>> ans =
[]
This is all part of a pretty big project, so it's hard to give the full context, but if it's possible from this, can someone explain why setting superclass data works for B but not A?
If it makes a difference B is returning a container.Map and A is returning 2xn matrix.
As far as I can tell from the documentation, it should work.

how to change value in map.continer child class

i have this superClass
classdef SysSignal<handle
%SIGNALP Summary of this class goes here
% Detailed explanation goes here
properties (SetAccess = public, GetAccess = public )
SetOfSignal = containers.Map('KeyType','char', 'ValueType', 'any')
end
methods
%constructor
function sys=SysSignal()
end
function sys=adds(sys,varargin)
%convert form cell to signalup
for n=1:length(varargin)
signal=varargin{1,n};
if isempty(signal.name)
continue
else
%add to the map
sys.SetOfSignal(signal.name)= signal;
end
end
end
and that child class
classdef Signalp<SysSignal
%SIGNALP Summary of this class goes here
% Detailed explanation goes here
properties
name
lineNo
color='red'
sumrole
end
properties (SetAccess=private,GetAccess=public)
arrPrice
LineLength
LineProportion
end
methods
%constructor
function sig=Signalp(varargin)
end
end
end
now i want to change the properties like this:
sys=SysSignal;
s=Signalp;
s.name='dd';
sys.adds(s)
sys.SetOfSignal('dd').sumrole='hello'
but i get that error :
??? Error using ==> subsasgn
Only one level of indexing is supported by a containers.Map.
how can i change the values from the superClass?
The answer is to seperate sys.SetOfSignal('dd').sumrole='hello' into two statements:
dd = sys.SetOfSignal('dd');
dd.sumrole='hello'
That is because sys.SetOfSignal('dd').sumrole doesn't do what you'd intuitively think it does. Indeed the containers.Map class overloads the subscripted reference and subscripted assignment operators. In essence they 'intercepts' the (), {} and . operators at the same time (ie .sumrole is 'sent' to the map.Containers object - instead of your object!). In my opinion that's a really weird design decision but we must live with it!
Have a look at these links for more info:
subsref, subsasgn
gregswiss's answer is correct, except that accessing the containers map creates a copy, so you finish by replacing the old value with the new modified one
dd = sys.SetOfSignal('dd');
dd.sumrole='hello'
sys.SetOfSignal('dd') = dd;

Is it possible in one line to get a class value from a function and modify it?

If I have a class
classdef foo
properties
a = 0;
end
methods
function obj foo(obj)
obj.a = 5;
end
end
end
And a function
function result = GetFoo()
result = foo();
end
At the command interpreter:
>> x = GetFoo()
x =
foo
Properties:
a: 5
Methods
>> x.a = 10
x =
foo
Properties:
a: 10
Methods
this yields an instance of foo and the value 'a' can be assigned. However, doing the same in one step:
>> GetFoo().a = 10
GetFoo =
a: [1x1 struct]
This creates a new structure called GetFoo that overrides the class and gives it a member called 'a'. Rather than the code getting the result of GetFoo() (the class instance) and settings its property 'a' = 10, it does this instead. I can see that it is likely a hangover from the ability to create weakly typed structures on the fly and the code having to be backward compatible It also seems to be related to the fact that MATLAB has no concept of a pointer so every input/output argument is a deep copy and that the above even if it would work would be setting the value of a copy of the value GetFoo() is using to source its return object, then throwing it away.
Nonetheless the goal really is to be able to do all the work I need without creating and requiring to clear temporary variables. The intent is code maintainability as much as cosmetic style.
You're mixing together quite a few different issues/complaints in your question, but I suspect what you're looking for is a handle class. Inherit your class from handle (i.e. write classdef foo < handle, and your class will have what is basically pass-by-reference behavior. You're right that MATLAB doesn't use pointers, but with handle classes it does have references.
Separately, it's not possible in MATLAB to index in to the output of a function (i.e. to write GetFoo.a or GetFoo().a - you do need a temporary variable for that, whether or not it returns a value or handle class.
Note that in your example above, the result of the GetFoo().a = 10 is not an instance of foo with the property a equal to 10 - it is a structure with a field a equal to 10. Type class(GetFoo), and you'll see it's a struct, not a foo.
This is really ugly, but is just to raise the glove that was thrown about doing it in one line. :-)
First of all, I'll modify a bit the class so you'll see that the constructor is called:
classdef foo
properties
a = 0;
end;
methods
function obj = foo()
obj.a = 5;
display('foo!');
end;
end;
end
And the one-liner, ran in Command Window:
>> subsasgn(GetFoo(), struct('type', '.', 'subs', 'a'), 10);
foo!

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]

cannot update class definition in Matlab

I am running into an infuriating problem with Matlab, and an earlier answer to apparently the same problem didn't help me, unfortunately. I apologize that the question is rather long - you need quite a bit of information to reproduce the problem (I tried to trim it as much as I could...)
The problem is this: No matter what I do, after I have used a class I cannot "make Matlab forget". Values used seem to be persistent, and edits to the class definition won't "stick". In the latter case, the error message is:
Warning: The class file for 'myClass' has been changed; but the change
cannot be applied because objects based on the old class file still
exist. If you use those objects, you might get unexpected results. You
can use the 'clear' command to remove those objects. See 'help clear'
for information on how to remove those objects.
I get that message even after
>> clear all
>> clear functions
>> clear ans
Somehow the class definition is persistent despite my attempts to clear it. To make matters worse, when I modify a value of an instance of the class, then clear it, the value is somehow not "forgotten". To illustrate, here is the source code of myClass:
% a simple class definition that shows the problem that I cannot
% figure out how to redefine a class without restarting Matlab
classdef myClass < handle
properties
precursors = {'none'};
numPre = {1};
value = 1;
end
methods
function obj = myClass(pre, num, val)
% constructor
if nargin > 0
obj.precursors = pre;
obj.numPre = num;
obj.value = val;
end
end
function v = sumVal(obj)
% find the sum of the value of all precursors
n = numel(obj.precursors);
v = 0;
for ii = 1:n
pc = obj.precursors{ii};
if isa(pc, 'myClass')
if ii==1
v = 0;
end
v = v + sumVal(pc) * obj.numPre{ii};
else
v = obj.value;
end
end
end
end
% only the following named instances may exist:
enumeration
grandpa ({'none'}, {1}, 1)
father ({myClass.grandpa}, {3}, -1)
son ({myClass.father}, {2}, -1)
end
end
In a fresh instance of Matlab, I do the following:
>> son = myClass.son;
>> sumVal(son)
ans =
6
>> grandpa = myClass.grandpa;
>> grandpa.value = 5;
>> sumVal(son)
ans =
30
So far, so good. The sumVal function discovers the fathers and grandfathers, and the sumVal is computed correctly (6 * 1 in the first case, 6 * 5 in the second case).
Now I delete "everything" (I think):
>> clear all
>> clear functions
>> clear ans
And I create just one variable:
>> son = myClass.son;
Now comes the kicker - the unexpected answer
>> sumVal(son)
ans =
30
When I inspect the variables loaded, I find
>> whos
Name Size Bytes Class Attributes
son 1x1 112 myClass
There is no grandpa instance, and the class definition file was not touched. Yet, the value of grandpa (which I created, then deleted) is somehow persistent.
And when I make a small change to the myClass.m file, and try to create a new variable (after a clear all), I get the message shown above. All of which leads me to my question:
Where is Matlab hiding an instance of my class so that variables are persistent after a clear all, and how do I clear the workspace (without restarting) so the class definition is "reset"?
I don't know if it matters, but I'm using Matlab 7.14.0.739 (R2012a)
You have an intermediate instance myClass.father that is not being destroyed by MATLAB. You have to deleteit yourself
>> clear grandpa
>> delete(son.precursors{1})
>> clear son
>> clear classes
>> son = myClass.son
son =
son
>> sumVal(son)
ans =
6
Edit:
Alternatively, you can add a destructor to your class
function delete(obj)
if isa(obj.precursors{1}, 'myClass')
delete(obj.precursors{1});
end
end
and use delete(son) instead of leaving it to clear function to destroy. You can extend this to your case and recursively delete all instances in your tree.
Those instances are "hiding" in the myClass enumeration class itself. Matlab is storing a reference to each of those named instances so when you reference them like myClass.father you get the same object back, instead of it constructing a new one. Probably similar to how values are stored in Constant properties on classes.
If you have any other classes that refer to the myClass.xxx enumerated instances in Constant properties, enumerations, or persistent variables, they could also be holding on to references to them.
Try doing clear classes a few times in a row instead of just once.
To help debug this, you could put a couple debugging printf() statements in the constructor and destructor for this class, so you can see when the instances are really created and cleaned up.
function obj = myClass(pre, num, val)
% constructor
if nargin > 0
obj.precursors = pre;
obj.numPre = num;
obj.value = val;
end
printf('myClass: created (%d, %d, nargin=%d)\n', obj.numPre, obj.value, nargin);
end
function delete(obj)
printf('myClass: deleting (%d, %d)\n', obj.numPre, obj.value);
end