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

 Réponse acceptée

Matt J
Matt J le 15 Juil 2021
Modifié(e) : Matt J le 15 Juil 2021
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 commentaires

Matt J
Matt J le 15 Juil 2021
Modifié(e) : Matt J le 15 Juil 2021
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.
Matt J is correct and this is documented on this documentation page.
Thanks, this indeed solves the problem!

Connectez-vous pour commenter.

Plus de réponses (0)

Catégories

En savoir plus sur Construct and Work with Object Arrays dans Centre d'aide et File Exchange

Produits

Version

R2020b

Community Treasure Hunt

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

Start Hunting!

Translated by