Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MATLAB Force constructor method to be called when assigning default array elements

Tags:

matlab

I have a class that assigns an immutable UUID to the object in its constructor. The following is a simplified illustration:

classdef mytest    
    properties (GetAccess = public, SetAccess = immutable)        
        uuid        
    end    
    properties
        val
    end
    methods        
        function obj = mytest(valIn)
            obj.uuid = char(java.util.UUID.randomUUID.toString);
            if nargin < 1
                valIn = 0;
            end
            obj.val = valIn;
        end
    end
end

This is working great in general, but I just discovered an issue with MATLAB's behaviour when assigning default elements to an array. I had assumed that if I typed

>> a(5) = mytest(2);

the constructor would be called 5 times - 4 times with no input arguments, to fill the default elements 1 to 4 of the array, and once with input argument 2 to assign the final element.

However, that's not what MATLAB does - instead it calls the constructor only once with no inputs, then copies the result four times to fill elements 1 to 4 (and then as expected for the final element). That means that the UUIDs ef elements 1 to 4 end up the same:

>> {a.uuid}'
ans = 
    '4424b91b-0977-4b4c-b18b-c4564875b952'
    '4424b91b-0977-4b4c-b18b-c4564875b952'
    '4424b91b-0977-4b4c-b18b-c4564875b952'
    '4424b91b-0977-4b4c-b18b-c4564875b952'
    'dbb8d862-8a1c-4bf9-876f-ef786e11a896'

It turns out this is documented behaviour that I just didn't expect, and I kind of understand why MathWorks have chosen to do that (you might not want the overhead of calling a no-input constructor many times separately).

But it's not the behaviour I want for this class - does anyone know of a way to force the constructor to be called for each element? Or perhaps you can suggest a different class design that would have the desired behaviour?

PS I did investigate whether MATLAB might be copying these default elements using a copy method - in which case inheriting my class from matlab.mixin.Copyable, and overriding the behaviour of copyElement might help - but it looks like that's not how it does the copying :(.

like image 357
Sam Roberts Avatar asked Feb 05 '16 10:02

Sam Roberts


1 Answers

Disclaimer: I'm not too familiar with MATLAB classes.

Looking at the relevant docs it seems that you're doing everything right, and so is MATLAB:

a(1,7) = SimpleValue(7)

The object assigned to array element a(1,7) uses the input argument passed to the constructor as the value assigned to the property:

...

MATLAB created the objects contained in elements a(1,1:6) with no input argument. The default value for properties empty [].

...

MATLAB calls the SimpleValue constructor once and copies the returned object to each element of the array.

This suggests that what you're experiencing is documented behaviour: automatic allocation of previously unassigned array elements is done with a single call to the constructor with zero input arguments.

This is also in agreement with another example using a random initializer: the example code uses

for k = 1:5
   a(k) = ObjProp;
end

to set the 5 elements of the array such that they contain different random data. At least from the documentation, this seems to be the work-around for your problem: initializing each empty element by hand (which is probably not what you want to do).

like image 178


Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!