Infinite recursion when saving a custom object

2 ビュー (過去 30 日間)
Claudio Vergari
Claudio Vergari 2021 年 12 月 3 日
コメント済み: Claudio Vergari 2021 年 12 月 3 日
I have a Parent and a Child object, and I need to store a reference to the Parent in the Child. It works, but I cannot seem to save the object because Matlab goes into an infinite loop.
Here is a working example:
classdef Parent
properties
Child = [];
Color = 'Red';
end
methods
function ret = get.Child(this)
% Returns a Child instance, with this Box as a parent
ret = Child(this);
end
end
end
classdef Child
properties
Parent = [];
end
methods
function this = Child(Parent)
% Initialize by saving a reference to the Parent
if exist('Parent' , 'var')
this.Parent = Parent;
end
end
function ParentColor(this)
% Display the parent's color
disp(['My Parent is ' this.Parent.Color])
end
end
end
% This works
P = Parent();
P.Child.ParentColor
% This goes into an infinite loop
save('D:\matlab_recursion\Box.mat', 'P')
When saving, Matlab starts looping between get.Child and and Child's initialization.
Any ideas on why this happens, and how I could solve it?
In real life, it would not be practical to just store the parent's Color property in the child because I need to access A LOT of properties and methods of the parent...
  2 件のコメント
Matt J
Matt J 2021 年 12 月 3 日
編集済み: Matt J 2021 年 12 月 3 日
I need to access A LOT of properties and methods of the parent...
That sounds like it might be better to make the child a sub-class of the parent.
Claudio Vergari
Claudio Vergari 2021 年 12 月 3 日
It could, I'll think about that. My child class is a "calculator" that computes stuff on the data in the parent class. The methods of my child could be methods of the parent, but I separate them to have a more logical organization. If I sub-classed the parent, I would have to make a copy of all the data in the parent when I want to compute stuff, and I don't want that.

サインインしてコメントする。

採用された回答

Matt J
Matt J 2021 年 12 月 3 日
編集済み: Matt J 2021 年 12 月 3 日
It happens because save() does know that the parent and child properties are supposed to be references to one another. It tries to de-reference all the property values when saving.
Here is a remedy:
classdef Parent<handle %<----make this a handle class
properties
Child = [];
Color = 'Red';
end
methods
function obj = Parent
obj.Child=Child(obj); %<---create the child in the constructor
end
end
end
classdef Child
properties
Parent = [];
end
methods
function obj = Child(p)
% Initialize by saving a reference to the Parent
if nargin
obj.Parent = p;
end
end
function ParentColor(obj)
% Display the parent's color
disp(['My Parent is ' obj.Parent.Color])
end
end
end
  3 件のコメント
Matt J
Matt J 2021 年 12 月 3 日
編集済み: Matt J 2021 年 12 月 3 日
Matlab has a copy-and-write system, meaning that if you create a structure like this in the Matlab workspace,
data=rand(512,512,512); % 1 GB of RAM
S.a=data;
S.b=data;
Matlab knows that S.a and S.b refer to the same data and so additional RAM is not allocated when the struct is created. (If you change even 1 element in either S.a or S.b, an additional 1-2 GB will be allocated). However, when you save S to a .mat file, the save() command is not smart enough to see that a and b are the same data. It just saves independent deep copies of both variables in the file, resulting in a file size of about 2 GB.
Claudio Vergari
Claudio Vergari 2021 年 12 月 3 日
Thank you so much for taking the time to explain. I think I undestand: when I assign the property at the parent's initialization, Matlab immediately makes a copy of the child object because stuff happens in the child's initialization. Whereas if I leave it for later, Matlab tries to "get" the property, which instead of referencing the Parent without copying it, this time it has to recompute the parent, which will reinitialize the child, etc..

サインインしてコメントする。

その他の回答 (0 件)

カテゴリ

Help Center および File ExchangeLoops and Conditional Statements についてさらに検索

製品


リリース

R2021a

Community Treasure Hunt

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

Start Hunting!

Translated by