Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Matlab class set method call unexpectedly

Tags:

oop

class

matlab

Matlab specifies When [a] Set Method is Called

I ran into odd results, so I conducted a series of tests on the following class:

% @cScenInsts/cScenInsts.m
%-------------------------

classdef cScenInsts < matlab.mixin.Copyable

properties
   TwinYrs = 5 % Default value
end % properties

methods

   function o = cScenInsts( TwinYrs_in ) % Constructor
      if exist('TwinYrs_in') && ~isempty( TwinYrs_in )
         o.TwinYrs = TwinYrs_in ;
      else
         o.TwinYrs = o.TwinYrs ;
      end % if
   end % function cScenInsts()

   function o = set.TwinYrs(o,TwinYrs_in)
      o.TwinYrs = TwinYrs_in;
      fprintf( '%s: Property TwinYrs = %g\n', mfilename, o.TwinYrs );
   end % function set.TwinYrs

end % methods

end % classdef

The else block is superfluous in this minimum working example, but in real life, I want it to invoke the set method, which sets the values of other dependent parameters.

Using the class definition above, I ran into mixed results in terms of whether they seemed to follow the rules for when a set method is called.

UNEXPECTED behaviour in the following command: "Assigning a property to its default value that is specified in the class definition" shouldn't trigger set method, but it does.

>> o = cScenInsts;
   cScenInsts: Property TwinYrs = 5

As well, "As an optimization, if MATLAB determines that a property value does not change as a result of an assignment referencing the property, MATLAB does not call the property set method". It seems that if the property is on the LHS and RHS of the assignment and the value doesn't change, the set method isn't called. This should apply above, as it is the else block that executes. The above result shows that it doesn't apply, which is the effect I seek. My anxt is that I don't know how much confidence I can have in the reliability of this behaviour in all circumstances when it seems to contradict the optimization provision.

EXPECTED behaviour in the following command:

>> o = cScenInsts(3);
   cScenInsts: Property TwinYrs = 3

UNEXPECTED behaviour in the following command: "Assigning a property to its default value that is specified in the class definition" shouldn't trigger set method, but it does.

>> o = cScenInsts(5);
   cScenInsts: Property TwinYrs = 5

EXPECTED behaviour in the following command:

>> o.TwinYrs = 3;
   cScenInsts: Property TwinYrs = 3

EXPECTED behaviour in the following command, since the property's AbortSet attribute not set to true

>> o.TwinYrs = 3;
   cScenInsts: Property TwinYrs = 3

UNEXPECTED behaviour in the following command: "Assigning a property to its default value that is specified in the class definition" shouldn't trigger set method, but it does.

>> o.TwinYrs = 5;
   cScenInsts: Property TwinYrs = 5

AMBIGUOUS behaviour in the following command: On one hand, "[a]ssigning a property to its default value that is specified in the class definition" shouldn't trigger set method, but it does. On the other hand, it can also be considered expected behaviour, since the property's AbortSet attribute not set to true

>> o.TwinYrs = 5;
   cScenInsts: Property TwinYrs = 5

Can anyone please explain the unexpected and/or ambiguous results?

like image 834
user36800 Avatar asked Apr 18 '18 17:04

user36800


2 Answers

I'll address each of the confusing bullet points you mention from this list of cases when the property set method IS NOT called:

  • Initializing default values in class definitions when loading the class

    I believe this is specifically referring to creating a class object by loading it from a MAT-file (i.e. using the loadobj method). When loading the property values, they are simply copied without passing them to the set method.

  • Assigning a property to its default value that is specified in the class definition

    I believe this is specifically referring to when MATLAB initially creates the object and sets its default values. It does this without passing the values to any set methods first. To see this, you can add this line to the very beginning of your class constructor:

    disp(o);
    

    When you run your code, you'll see that a default object with the default property values is already created for you upon entering the constructor, before you've even done anything with the input arguments. These properties are set without invoking any set methods (as the bullet point states). Any subsequent changes to the property, like when you set them in your if-else statement, DOES still invoke the set method, as expected.

    You may notice then that your else statement is actually unnecessary in this case, since the defaults are already set. Removing the else statement will give you your expected behavior for:

    o = cScenInsts;
    

    As an additional aside, since you are subclassing the matlab.mixin.Copyable class (which has handle class behavior), you don't need to return an object from your set methods:

    function set.TwinYrs(o, TwinYrs_in)
      ...
    


  • As an optimization, if MATLAB determines that a property value does not change as a result of an assignment referencing the property, MATLAB does not call the property set method.

    This statement is a little unclear. As you already noted, leaving the AbortSet attribute unset (i.e. it is set to false by default) means that the set method will still be called even when setting a property to the same value. The statement above seems to suggest that under some circumstances, even when the AbortSet attribute is false, MATLAB may still decide to forego calling the set method. If so, it's not clear what those conditions are under which that optimization is used.

Removing the else statement as I suggest above, here are the expected results for some of your examples above:

>> o = cScenInsts;  % Set method not invoked, default value used

>> o = cScenInsts(3);
cScenInsts: Property TwinYrs = 3  % Set method invoked, overriding default value

>> o = cScenInsts(5);
cScenInsts: Property TwinYrs = 5  % Set method invoked, even though same as default value
                                  %   (since AbortSet is false)
>> o.TwinYrs = 5;
cScenInsts: Property TwinYrs = 5  % Set method invoked, even though same as current value
                                  %   (since AbortSet is false)
like image 137
gnovice Avatar answered Oct 19 '22 09:10

gnovice


This is the answer from TMW:

...the statement:

"As an optimization, if MATLAB determines that a property value does not change as a result of an assignment referencing the property, MATLAB does not call the property set method."

...is plainly incorrect. This optimization does not exist -- the only time MATLAB forgoes calling the setter due to an assignment not changing the value is when "AbortSet" is set to true.<...snip...>

As for the other unclear bullet points:

"Initializing default values in class definitions when loading the class"

This refers to loading the class definition which happens when doing “?” or when first constructing the class. This is the step that parses and compiles the class definition and sets the DefaultValue property of the meta.property object accessible from the meta.class object returned from ?. This has nothing to do with loading instances of a class from a MAT-File or loadobj.

"Assigning a property to its default value that is specified in the class definition"

This bullet means that the set-function is not called when MATLAB assigns a default value to a property when making a new instance of a class. This refers to the assignment of the default value during property initialization. As we suspected, it does not refer to any other assignment to a value that happens to be equal to the default value.

I will go ahead and submit the documentation update request...

Thank you all for having chimed in.

like image 44
user36800 Avatar answered Oct 19 '22 10:10

user36800