2013-06-21 1 views
4

Я столкнулся с проблемой беспризорности с Matlab, и earlier answer, по-видимому, эта же проблема не помогла мне, к сожалению. Я прошу прощения, что вопрос довольно длинный - вам нужно довольно много информации, чтобы воспроизвести проблему (я попытался обрезать ее как можно больше ...)не может обновить определение класса в Matlab

Проблема в том, что независимо от того, что я делаю, после того, как я использовал класс, я не могу «заставить Matlab забыть». Используемые значения кажутся постоянными, и изменения в определении класса не будут «прилипать». В последнем случае сообщение об ошибке:

Предупреждение: файл класса для 'myClass' был изменен; но изменение не может быть применено, поскольку существуют объекты, основанные на файле старого класса, все еще . Если вы используете эти объекты, вы можете получить неожиданные результаты. Вы можете использовать команду 'clear' для удаления этих объектов. . См. «Помощь очистки» для получения информации о том, как удалить эти объекты.

Я получаю это сообщение, даже после того, как

>> 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 и пытаюсь создать новую переменную (после clear all), я получаю сообщение, показанное выше. Все это приводит меня к моему вопросу:

Где Matlab скрывает экземпляр моего класса, чтобы переменные были постоянными после clear all и как очистить рабочее пространство (без перезапуска), чтобы определение класса было «сброшено», ?

Я не знаю, имеет ли это значение, но я использую Matlab 7.14.0.739 (R2012a)

+1

Вы также попробовали «ясные классы»? –

+0

@DavidK - когда я все делаю; clear classes' Я получаю '' Предупреждение: существуют объекты класса myClass. Невозможно очистить этот класс или любой из его суперклассов. "' И после этого 'sumVal (son)' по-прежнему '30' ... – Floris

+0

Почему вы ожидаете, что 'sumVal (son)' не будет 30 в любой момент? Вы пытаетесь изменить структуру дерева во время выполнения? –

ответ

6

У вас есть промежуточный экземпляр myClass.father, который не уничтожается MATLAB. Вы должны delete это себе

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

Edit: В качестве альтернативы, вы можете добавить деструктор в класс

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

и использовать delete(son) вместо того, чтобы оставить его clear функцию, чтобы уничтожить. Вы можете распространить это на свой случай и рекурсивно удалить все экземпляры в своем дереве.

+0

Brilliant! Это открытие попадает в суть моей проблемы! В этом случае вы показываете конкретный способ очистки рабочей области; но есть ли способ отбросить эти скрытые экземпляры (реальное дерево классов намного сложнее - мне нужно создать свой собственный метод 'destroyClass', чтобы убить их всех? Можете ли вы сделать это из самого класса? – Floris

+0

Вы можете добавить деструктор, чтобы позаботиться о промежуточных объектах.Я обновил ответ, чтобы проиллюстрировать это для примера. –

+0

Мы приближаемся. Я все еще могу попасть в неприятности. Я могу создать «сына» без предварительного создания 'father' - и если я попытаюсь удалить' son', я получаю сообщение об ошибке (потому что 'obj.precursors {1}' не существует). Такая же проблема возникает, если я удаляю объекты в неправильном порядке. заключается в том, что я попал в состояние, в котором Matlab жалуется на объекты старого класса, но ни одна из ваших методик не работает - даже если я создаю нового «отца» и «сына», когда я удаляю «сына», он жалуется, что предшественник Нет. Вернуться к основному вопросу: как мне найти (перечислить, перечислить) скрытый bjects? – Floris

2

Эти экземпляры «скрываются» в классе перечисления myClass. Matlab хранит ссылку на каждый из этих именованных экземпляров, поэтому, когда вы ссылаетесь на них, как myClass.father, вы получаете тот же объект обратно, вместо него создаете новый. Вероятно, похоже на то, как значения хранятся в свойствах классов Constant.

Если у вас есть какие-либо другие классы, которые относятся к myClass.xxx перечисленным случаям в Constant свойств, перечисления или persistent переменных, они также могут быть держась ссылки на них.

Попробуйте сделать 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 
+0

Верно, что несколько вызовов 'clear classes', похоже, работают, но это очень неудовлетворительно. Я попробую ваш отладочный трюк, чтобы получить лучшую ручку. Мой фактический класс более сложный - например, есть несколько путей к одному и тому же предку. Я обнаружил, что единственным надежным решением пока является сценарий, который вызывает 'delete()' на каждой позиции моего класса (их более 20) «вручную». Мне хотелось бы получить список всех экземпляров в памяти. – Floris

+0

Что вы находите неудовлетворительным в отношении повторения «ясных классов»? –

+0

Возможно, вы можете получить список всех экземпляров перечисления с 'm = enumeration ('myClass')'. См. Http://www.mathworks.com/help/matlab/ref/enumeration.html. Это позволит вам обрабатывать их в цикле вместо «вручную», выполняющих каждый. –