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