Matlab:关于句柄变量和 mat 文件的文档?[已结束]

Matlab: Documentation on handle variables and mat files? [closed]

提问人:user2153235 提问时间:3/16/2016 最后编辑:user2153235 更新时间:3/22/2016 访问量:224

问:


我们不允许向读者、工具、软件库等寻求推荐的问题。您可以编辑问题,以便用事实和引文来回答。

7年前关闭。

是否有任何关于在保存和加载 mat 文件时如何处理句柄变量的 TMW 文档?通过反复试验,我确定了基本行为,例如,底层对象存储到 mat 文件中,并从 mat 文件加载,但实际的类定义本身不是。也就是说,如果您加载了一个句柄对象,但您的类定义已通过添加字段进行了修改,则加载的对象将具有这些附加字段,尽管它们不会使用值进行初始化。

对于那些在面向对象编程中定义句柄类的人来说,更全面的设计行为文档是必不可少的。例如,如果将对象 A 保存到 mat 文件,并且它具有引用对象 Z 的属性,那么将对象 B 保存到 mat 文件,并且它还包含引用对象 Z 的属性,该怎么办?如果我分别加载两个 mat 文件,我是否会有两个单独的对象 Z 实例,或者这两个变量会引用同一个对象?

另一种情况可能是两个句柄对象变量引用同一个对象,但一个变量在基本工作区中,而另一个变量实际上是另一个对象的属性?如果我保存并加载,这两个变量是否仍指向同一个对象?

我知道我可以凭经验对每种可能的情况进行逆向工程,但这比阅读行为规范(如果存在)效率低得多。

MATLAB OOP 句柄

评论

0赞 Phil Goddard 3/16/2016
您是否看过对象的保存和加载过程?它描述了如何使用 saveobj 和 loadobj 方法来正确处理保存和加载,以及当对象定义发生更改时会发生什么情况。
0赞 user2153235 3/16/2016
我很欣赏这个链接,菲尔,但我担心我可能通过提供我逆向工程的例子来混淆这个问题。我实际上是在寻找如何处理句柄类对象变量。我不认为它们是“正常”的对象变量,因为它们更像是参考变量(用C++白话来说,如果我正确地记得10+年前的C++的话)。我将修改问题以澄清。

答:

4赞 Jonas 3/16/2016 #1

只要 Matlab 句柄对象在内存中,就会通过引用传递它们。但是,当它们被保存并重新加载时,它们是一个新对象,因此,对它们的任何引用都是“断开的”(参见下面的示例)。对于类句柄的所有对象都是如此,无论您构造的情况多么复杂(例如,作为其属性的属性又是 的属性,在重新加载后会突然占用更多的内存):从磁盘加载对象会创建一个新的、未引用的实例。objectAobjectBobjectA

objA = myHandleObject();
objB = objA; %# same object, changing A changes B
save('objOnDisk.mat','objB');
load('objOnDisk.mat') %# overwrites objB in the workspace
%# objB is no longer a reference of objA

如果您在集群上的循环中修改句柄对象,这一点尤其明显,因为工作区会被保存并重新加载到各个工作线程上。parfor

有一种方法可以解决它:您可以定义函数来查找同一类的其他对象,并且如果为每个对象添加唯一的引用编号(例如,将属性设置为 ),则可以手动“重建”引用。去过那里,做过,但不能推荐,因为它很快就会变得非常复杂。loadobjtempname

评论

0赞 user36800 3/17/2016
谢谢乔纳斯。我认为这是针对特定情况的一个很好的答案。但是,我真的希望有关于保存/加载句柄对象的主要场景的文档。例如,如果我有 2 个变量引用同一个对象怎么办?更复杂的是,如果一个在基本工作区中,而另一个是另一个对象的属性,该怎么办?如果我使用单独的语句加载这两个对象中的每一个,会怎样?我可以测试每个场景,但我希望这不是必需的,即记录与处理对象相关的保存/加载的整体行为。
0赞 user36800 3/17/2016
我说过,这个问题与一般文档有关,而不是与特定场景有关。所以我投了赞成票,而不是接受答案。但是,我对没有接受复选标记图标感到困惑。根据接受答案的元页面,唯一的时间限制是必须在问题发布后等待 15 分钟。
0赞 Jonas 3/17/2016
@user36800:我加了几句话来澄清这确实是一种普遍的行为,而不仅限于我提供的例子。希望这会有所帮助。
0赞 user36800 3/18/2016
谢谢,乔纳斯。我将跟进(一旦我可以使用Matlab访问机器)以检查最终场景:一个变量在基本工作区中,另一个变量是基本工作区中对象的属性,两者都引用同一个对象。我将保存整个工作区,对于测试 1,加载整个工作区以确认它们都引用同一个对象。测试 2 是仅加载引用变量,然后加载其属性引用同一对象的对象。对于测试 2,我希望您在答案中展示结果。对于测试 1...我们拭目以待。
0赞 user36800 3/18/2016
但我认为,最初问题的答案是没有关于这些小细节的文档(我敢肯定有些场景是我没有预料到的)?如果是这样,我将看看 TMW 是否愿意在他们的文档中包含此类行为描述。否则,人们就会对行为进行逆向工程。
1赞 user36800 3/19/2016 #2

我要感谢受访者。他们的回答非常有帮助。但是,问题在于是否记录了句柄对象变量的保存/加载行为。答案似乎是否定的,我会问TMW他们是否觉得值得记录这一点。

除了 Jonas 关于保存/加载行为的信息之外,我还创建了以下测试,以确定 (i) 加载整个工作区与 (ii) 单个句柄对象变量时加载行为的差异。正如我在注释中推测的那样,在情况 (i) 中,对同一对象的多个句柄保持对公共对象的引用,但在情况 (ii) 中,它们引用单独的(但相同的)对象:

% myClassA.m
%-----------
% Handle class
classdef myClassA < handle
properties
   myPropA
end % properties
end % classdef

% myClassB.m
%-----------
% The property will refer to a
% handle class object
classdef myClassB
properties
   myObjA
end % properties
end % classdef

% test.m
%--------
% Main test script, uses the two
% classes
clc
echo on

% Create 2 object variables. 2nd
% one has a property that refers to
% same object as the first one
objA = myClassA
objA.myPropA = 5
objB = myClassB
objB.myObjA = objA

% Check that changes in handle object
% is seen from both variables
objA.myPropA = 7
objB.myObjA.myPropA % Should be 7

% Save & load entire workspace.
% Check that both variables refer
% to same object.
save('myWrkSpc')
clear classes
load('myWrkSpc')
objA
objB.myObjA
objA.myPropA = 9
objB.myObjA % Should be 9

% Load variables individually. Show
% that they now refer to separate
% objects
clear classes
load('myWrkSpc','objA')
load('myWrkSpc','objB')
objA
objB.myObjA
objA.myPropA = 9
objB.myObjA
   % Should still be 7 instead of 9

echo off

这些是我迄今为止遇到过的场景,尽管我相信我会遇到新的场景,在这些场景中,对设计行为进行详尽的文档会有所帮助。