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.
1 Answer 1
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.
-
\$\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\$littleBOT– littleBOT2019年12月17日 21:56:27 +00:00Commented Dec 17, 2019 at 21:56