2
\$\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.

\$\endgroup\$
2
\$\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.

| improve this answer | |
\$\endgroup\$
  • \$\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 Dec 17 '19 at 21:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.