4

我在使用 Matlab 时遇到了一个令人恼火的问题,不幸的是,对显然相同问题的早期答案对我没有帮助。我很抱歉这个问题很长 - 你需要相当多的信息来重现这个问题(我试图尽可能多地修剪它......)

问题是这样的:无论我做什么,在我使用了一个类之后,我都不能“让 Matlab 忘记”。使用的值似乎是持久的,对类定义的编辑不会“坚持”。在后一种情况下,错误消息是:

警告:“myClass”的类文件已更改;但无法应用更改,因为基于旧类文件的对象仍然存在。如果你使用这些对象,你可能会得到意想不到的结果。您可以使用“清除”命令删除这些对象。有关如何删除这些对象的信息,请参阅“帮助清除”。

即使在之后我也收到了这条消息

>> clear all
>> clear functions
>> clear ans

尽管我试图清除它,但不知何故类定义是持久的。更糟糕的是,当我修改类实例的值,然后将其清除时,该值不会以某种方式“被遗忘”。为了说明,这里是源代码myClass

% a simple class definition that shows the problem that I cannot
% figure out how to redefine a class without restarting Matlab
classdef myClass < handle
    properties
        precursors = {'none'};
        numPre = {1};
        value = 1;
    end

    methods
        function obj = myClass(pre, num, val)
            % constructor
            if nargin > 0
                obj.precursors = pre;
                obj.numPre = num;
                obj.value = val;
            end
        end
        function v = sumVal(obj)
            % find the sum of the value of all precursors
            n = numel(obj.precursors);
            v = 0;
            for ii = 1:n
              pc = obj.precursors{ii};
              if isa(pc, 'myClass')
                  if ii==1
                      v = 0;
                  end
                  v = v + sumVal(pc) * obj.numPre{ii};
              else
                  v = obj.value;
              end
            end
        end
    end

    % only the following named instances may exist:
    enumeration
      grandpa   ({'none'},           {1},  1)
      father    ({myClass.grandpa},  {3}, -1)
      son       ({myClass.father},   {2}, -1) 
    end
end

在一个新的 Matlab 实例中,我执行以下操作:

>> son = myClass.son;
>> sumVal(son)

ans = 

     6

>> grandpa = myClass.grandpa;
>> grandpa.value = 5;
>> sumVal(son)

ans =

    30

到目前为止,一切都很好。该sumVal函数发现父亲和祖父,并且sumVal计算正确(第一种情况下为 6 * 1,第二种情况下为 6 * 5)。

现在我删除“一切”(我认为):

>> clear all
>> clear functions
>> clear ans

我只创建一个变量:

>> son = myClass.son;

现在来了踢球者 - 出乎意料的答案

>> sumVal(son)

ans =

    30

当我检查加载的变量时,我发现

>> whos
Name    Size       Bytes  Class     Attributes

son      1x1         112  myClass

没有grandpa实例,也没有触及类定义文件。然而,grandpa(我创建,然后删除)的价值在某种程度上是持久的。

当我对文件进行小的更改myClass.m并尝试创建一个新变量(在 a 之后clear all)时,我会收到上面显示的消息。所有这些都让我想到了我的问题:

Matlab 在哪里隐藏我的类的一个实例,以便变量在 a 之后保持不变clear all,以及如何清除工作区(不重新启动)以便类定义为“重置”?

我不知道这是否重要,但我使用的是 Matlab 7.14.0.739 (R2012a)

4

2 回答 2

6

myClass.father您有一个未被 MATLAB 销毁的中间实例。你必须delete自己做

>> clear grandpa
>> delete(son.precursors{1})
>> clear son
>> clear classes
>> son = myClass.son
son = 
    son    
>> sumVal(son)
ans =
     6

编辑:或者,您可以向您的课程添加一个析构函数

    function delete(obj)
        if isa(obj.precursors{1}, 'myClass')
            delete(obj.precursors{1});
        end
    end

并使用delete(son)而不是让它clear发挥破坏作用。您可以将此扩展到您的案例并递归删除树中的所有实例。

于 2013-06-21T19:25:26.610 回答
2

这些实例“隐藏”在 myClass 枚举类本身中。Matlab 正在存储对每个命名实例的引用,因此当您引用它们时,就像myClass.father您得到相同的对象一样,而不是构造一个新的对象。可能类似于值如何存储在Constant类的属性中。

如果您有任何其他类引用属性、枚举或变量myClass.xxx中的枚举实例,它们也可能会保留对它们的引用。Constantpersistent

尝试clear classes连续做几次而不是一次。

为了帮助调试,你可以在这个类的构造函数和析构函数中放置几个​​调试printf()语句,这样你就可以看到实例何时真正被创建和清理。

  function obj = myClass(pre, num, val)
      % constructor
      if nargin > 0
          obj.precursors = pre;
          obj.numPre = num;
          obj.value = val;
      end
      printf('myClass: created (%d, %d, nargin=%d)\n', obj.numPre, obj.value, nargin);
  end
  function delete(obj)
      printf('myClass: deleting (%d, %d)\n', obj.numPre, obj.value);
  end
于 2013-07-01T05:29:15.370 回答