3
\$\begingroup\$

AFAIK Octave still does not support enumerations, so I've done my best to write a workaround. The question is if there is something missing in code below, or maybe something can be improved?

The reason for the enumConstructor method is that with Octave 4.2.0 I had errors when overloading the constructor.

classdef Enum < handle
 methods (Static = true)
 function [out] = test ()
 out = Enum.enumConstructor("test");
 endfunction
 endmethods
 # implementation
 properties (Access = private)
 value
 endproperties
 properties (Dependent = true)
 Value
 endproperties
 methods (Access = private, Static = true)
 function [this] = enumConstructor (in_val)
 this = Enum();
 this.value = in_val;
 endfunction
 endmethods
 methods
 function [out] = get.Value (this)
 out = this.value;
 endfunction
 function [out] = getValue (this)
 out = this.value;
 endfunction
 function [out] = eq (this, in_obj)
 out = false;
 if isa(in_obj, "Enum")
 out = strcmp(this.value, in_obj.value);
 endif
 endfunction
 endmethods
endclassdef

Edit: I was a bit inspired with Java enumerations, rather than MATLAB.

Cris Luengo
6,9911 gold badge14 silver badges37 bronze badges
asked Dec 15, 2019 at 20:46
\$\endgroup\$
0

1 Answer 1

3
\$\begingroup\$

When I run your code in Octave I see the following:

>> a=Enum.test()
a =
<object Enum>

Simply overloading the disp operator will solve this issue:

 function disp(this)
 disp(['Enum with value ',this.value])
 end

Now:

>> a=Enum.test()
a =
Enum with value test

You created a handle class to define your enumerator object. I don't see the benefit of using a handle class for this. Handle classes are meant as an interface to resources (a file, memory) that cannot (or should not) be copied. The handle class is always passed by reference, and the assignment operator causes the new variable to refer to the same object rather than making a copy.

This means that a=Enum; function(a) can modify a. Also, b=a; b.Value='foo' will change the value of a. This is highly uncommon and unexpected behavior in the MATLAB language. In general, MATLAB/Octave data is never a handle class, and I think an enumerator class should not be a handle class either.


I'm not sure what problem enumConstructor is avoiding. I'm running Octave 5.1 and don't have any issues overloading the constructor. A static function is a good workaround. I'm not sure why it is marked private though, since this makes it impossible to create an object of the class (I'm assuming the method test is just for show, not actually meant as part of the class).


Octave has a few additions to the MATLAB language that I feel are unfortunate. I always suggest to people not to use these additions. In particular, comments should start with %, not with #, and you should use end rather than endfunction, endif, etc. I don't feel that these additions improve the language sufficiently to break comparability between the two systems.


When you define a function with a single output argument, the square brackets around the output are superfluous. Thus, instead of writing

function [out] = getValue (this)

you can write

function out = getValue (this)

The use of a private property to hold data, and a public, dependent property to read and write from it, adds unnecessary complexity. It is possible to define accessor functions to protect public properties. For example, if the class only had a public value property, then the function set.value(this, value) can prevent the user from changing the value to an illegal value. A function value = get.value(this) likewise can control the reading of the property. The advantage is that one does not need to define the reading property if it's not necessary (there are default property reading and writing functions if one doesn't explicitly define them).


Putting all these things together, I would implement an enumerator class this way:

classdef Enum
 properties
 value
 end
 methods
 function this = Enum(value)
 if nargin > 0
 this.value = value;
 else
 this.value = 'none';
 end
 end
 function this = set.value(this, value)
 if ~ischar(value) || ~any(strcmp(value, {'foo','bar','baz','none'}))
 error(['Illegal value! ', value])
 end
 this.value = value;
 end
 function out = eq(this, other)
 out = strcmp(this.value, other.value);
 end
 function disp(this)
 disp(['Enum with value ',this.value])
 end
 end
end

You can use it as follows:

a = Enum;
b = Enum('foo');
c = Enum('foo');
>> a==b
ans = 0
>> c==b
ans = 1

Alternatively, if you don't want to allow the user to change the value of the enumerator (which, I gues, is not really necessary at all), then it is possible to keep the value property as read-only (SetAccess=private), or even completely private (Access=private), and remove the set.value function. With a private value property, the Enum class can still be copied, examined (using disp) and compared.

answered Dec 17, 2019 at 17:58
\$\endgroup\$
1
  • \$\begingroup\$ OK, with once property it is indeed better to modify with restrictions in set.value. However if a specific combination is desired, like if one wanted to store game characters data in enum (name, age, etc) it seemed to me that putting each combination in static function would be the best. I didn't wrote about this use case however so its my bad. About enumConstructor it seems I was doing something wrong.. Anyway thank you for your time and review (: \$\endgroup\$ Commented Dec 17, 2019 at 21:56

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.