Clear Filters
Clear Filters

Object-Oriented: strange behavior that leads to shared reference

1 view (last 30 days)
Hi, is my understanding of Matlab OO incorrect or something else is going on here ?
I cannot explain why this code assert :
Given this simple handle class :
classdef TestA < handle
properties
Name string = "default value for TestA";
end
end
And using it like this ( see the explicit size of 1,1 )
classdef TestB < handle
properties
PropA (1,1) TestA % please note the (1,1) size
end
end
And this test usage :
b1 = TestB;
b1.PropA.Name = "in b1 object";
b2 = TestB;
b2.PropA.Name = "in b2 object";
assert(b1.PropA ~= b2.PropA)
This assertion failling clearly state that the PropA property of both objects b1 and b2 is the same object.
Is this a documented behaviour ?
I was expecting to get a new TestA object in every TestB object.
note that we get the same strange behavior with this syntax:
classdef TestB2 < handle
properties
PropA (1,:) TestA = TestA % please note the (1,:) size
end
end
So you get the strange behavior and you loose the (1,1) size constraint.
This can be a workaround, but again, far from clean and still no size constraint
classdef TestB3 < handle
properties
PropA (1,:) TestA = TestA.empty() % please note the (1,:) size
end
methods
function obj = TestB3()
obj.PropA = TestA(); % explicitly create the object works
end
end
end
I can get the size constraint by using a Dependent property but this is so much code for something that basic...
Should i report a bug? or is it explained somewhere in the documentation ?

Accepted Answer

Matt J
Matt J on 28 May 2024
Edited: Matt J on 28 May 2024
The reason this occurs is documented here. Default property values are only generated once when the classdef is first instantiated, and then copied to every new instance of the class. Since PropA's default is a handle object, this copying results in a shared initial PropA value in every instance of TestB. You must use a constructor call to create unshared instances of PropA.
If the size constraint is what you're after, can't you just do this?
classdef TestB < handle
properties
PropA (1,1) {mustBeA(PropA,"TestA")} = TestA()
end
methods
function obj = TestB()
obj.PropA = TestA();
end
end
end

More Answers (1)

Ganesh
Ganesh on 28 May 2024
Edited: Ganesh on 28 May 2024
The behaviour is expected and arises as you are using the "handle" class. When using a handle class, as opposed to a classic class, all objects of the class reference are the same. You might have noted that "b1.PropA.Name" and "b2.PropA.Name" have the same string at the end of your code.
You can also try the following:
classdef TestB < handle
properties
PropA (1,2) TestA
end
end
Now you have declared the array to be of size (1,2)
b1 = TestB;
b1.PropA(1).Name = "in b1 object";
disp(b1.PropA(2).Name) % will be "in b1 object"
b2 = TestB;
b2.PropA.Name = "in b2 object";
disp([b1.PropA(1).Name, b1.PropA(2).Name, b2.PropA(1).Name, b2.PropA(2).Name])
% all will be "in b2 object"
% in fact, all of them reference to the same object
assert(b1.PropA ~= b2.PropA)
For more information regarding the usage of "handle" class, refer to the following documentation:
Hope this helps!

Products


Release

R2024a

Community Treasure Hunt

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

Start Hunting!