Changing the content of an object that is contained with an array of objects

3 views (last 30 days)
The following code represents the sort of thing I need to do for an application. This is based on a top-level class called ObjectWithDataContainer.
classdef ObjectWithDataContainer < handle
properties
Data (1,1) DataContainer
end
end
This contains a property called Data whose class is DataContainer, which contains a dataitem called Value (with default set to zero).
classdef DataContainer < handle
properties
Value = 0
end
end
Now, create a vector of ObjectWithDataContainer and verify that both embedded Data values are 0. Then set one of the first Data value to 1 and again verify both Data values.
>> obj(1) = ObjectWithDataContainer ;
>> obj(2) = ObjectWithDataContainer ;
>> obj(1).Data
ans =
DataContainer with properties:
Value: 0
>> obj(2).Data
ans =
DataContainer with properties:
Value: 0
>> obj(1).Data.Value = 1 ;
>> obj(1).Data
ans =
DataContainer with properties:
Value: 1
>> obj(2).Data
ans =
DataContainer with properties:
Value: 1
Although only one Data value has been set, both Data values have been changed to that value.
What on earth is going on here?

Answers (1)

per isakson
per isakson on 27 May 2022
Edited: per isakson on 28 May 2022
The behavior you see is the way Matlab is designed to work. See Properties Containing Objects and Property Default Values. The key message is
"Evaluation of property default values occurs only when the value is first needed, and only once when MATLAB first initializes the class. MATLAB does not reevaluate the expression each time you create an instance of the class."
IMO: When you don't exactly know what you are looking for, these pages aren't that easy to find. And what exactly does "first needed" mean?
In your case the class, DataContainer, is first needed when obj(1) is created. (However, I failed to find that stated in the documentation.) In your objects, obj(1) and obj(2), the values of Data, are handles to the same underlying object of the class, DataContainer.
Anyhow, I replaced
Data (1,1) DataContainer
by
Data (1,1) % DataContainer
and added a contrucctor
function this = ObjectWithDataContainer()
this.Data = DataContainer();
end
Now the code works as you expect.
%%
obj(1) = ObjectWithDataContainer ;
obj(2) = ObjectWithDataContainer ;
%%
obj(1).Data.Value = 1;
obj(2).Data.Value = 2;
%%
obj(1).Data
ans =
DataContainer with properties: Value: 1
obj(2).Data
ans =
DataContainer with properties: Value: 2
  1 Comment
Dominic Diston
Dominic Diston on 22 Nov 2022 at 12:11
Thanks for the explanation and sorry for the delay in responded (I caught COVID and took a long time to recover fully).
I certainly didn't expect this to be a problem as the code apparently states what needs to happen. I categorize this as a "gotcha". It was difficult to isolate and identify. Obviously we should be doing things properly and be using constructors. More generally, MATLAB should allow us to do things in the way in which I originally did them.
This has really shaken my confidence in MATLAB. I now need to go through everything I have and see if the same feature exists anywhere. What a pain!!

Sign in to comment.

Categories

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

Community Treasure Hunt

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

Start Hunting!

Translated by