Applying method to one object in array affects values of another

I have an array of objects, but when I call a method of one object in the array, the values of other elements of the array change as well.
The code in question is as follows. A 2x2 array of the MixerArray class is initialised. When I call the method add on a(1,1), the values of a(1,2) and a(2,1) change as well. The following code gives an output of 0, 7 even though the add method should only change values of a(1,1)
a(2,2) = MixerArray();
disp(a(1,2).Register_Array.currentVal)
a(1,1).add(3,4);
disp(a(1,2).Register_Array.currentVal)
The class in question is as follows
classdef MixerArray < handle
properties
Register_Array % Array to store values
Length % Number of mixers
end
methods
function obj = MixerArray(n)
if nargin ==0
obj.Register_Array = RegisterArray();
obj.Length = 1;
else
obj.Register_Array = RegisterArray(n);
obj.Length = n;
end
end
% add function
function add(obj, A, B, i)
if nargin == 3
obj.Register_Array.setval(A+B);
else
obj.Register_Array.setval(A+B,i);
end
end
% Update function
function update(obj)
obj.Register_Array.update();
end
end
end
This calls upon a second class
classdef RegisterArray < handle
properties
lastVal % Last value
currentVal % Current value
end
methods
% n is the length of the register
function obj = RegisterArray(n)
if nargin == 0
obj.currentVal = 0;
obj.lastVal = 0;
else
obj.currentVal = zeros(1,n);
obj.lastVal = zeros(1,n);
end
end
% Assignment function
function setval(obj, new_value, i)
if nargin == 2
obj.currentVal = new_value;
else
obj.currentVal(i) = new_value;
end
end
% Update values
function update(obj)
obj.lastVal = obj.currentVal;
end
end
end

 Accepted Answer

It is a curious pitfall you've stumbled on. Basically, the solution is to avoid using default empty elements to fill up a MixerArray. Instead, create each element of the array explicitly within the constructor.
a=MixerArray(2,2);
where you would modify the constructor like the following
function obj = MixerArray(varargin)
if ~nargin, return; end
obj(varargin{:})=MixerArray();
for i=1:numel(obj)
obj(i).Register_Array=RegisterArray();
end
end

3 Comments

The reason this is necessary is because your original code
a(2,2) = MixerArray();
forces Matlab to fill a(1,1), a(1,2) and a(2,1) with default empty objects. However, it doesn't create these objects by calling the MixerArray constructor 3 separate times. It calls it only once and copies the resulting object into the 3 missing spots. But because the property Register_Array is a handle object, this copying uses handle copying semantics and therefore for i=1,2,3, every a(i).Register_Array is in fact the same instance.
Thanks, this indeed solves the problem!

Sign in to comment.

More Answers (0)

Categories

Find more on Construct and Work with Object Arrays in Help Center and File Exchange

Products

Release

R2020b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!