exponenta event banner

Поддержание совместимости классов

Переименовать свойство

Предположим, что вы хотите переименовать свойство, но не хотите вызывать ошибки в существующем коде, ссылающемся на исходное свойство. Например, переименование общедоступного свойства с именем OfficeNumber кому Location. Вот исходное определение класса:

classdef EmployeeList
   properties
      Name
      Email
      OfficeNumber % Rename as Location
   end
end

Использование скрытого зависимого свойства может привести к желаемым результатам.

  • В определении класса установите значение OfficeNumber атрибуты свойства для Dependent и Hidden.

  • Создание метода набора характеристик для OfficeNumber который устанавливает значение Location собственность.

  • Создание метода получения свойства для OfficeNumber который возвращает значение Location свойство location.

Пока OfficeNumber свойство скрыто, существующий код может продолжать доступ к этому свойству. Hidden атрибут не влияет на доступ.

Поскольку OfficeNumber является зависимым, избыточность в хранилище не требуется при добавлении нового свойства. MATLAB ® не хранит и не сохраняет зависимые свойства.

Вот обновленное определение класса.

classdef EmployeeList
   properties
      Name
      Email
      Location
   end
   properties (Dependent, Hidden)
      OfficeNumber
   end
   methods
      function obj = set.OfficeNumber(obj,val)
         obj.Location = val;
      end
      function val = get.OfficeNumber(obj)
         val = obj.Location;    
      end
   end
end

Сохранение и загрузка EmployeeList Объекты

Можно загрузить старые экземпляры EmployeeList в присутствии новой версии класса. Код, относящийся к OfficeNumber свойство продолжает работать.

Прямая и обратная совместимость

Предположим, что вы хотите иметь возможность загружать новые EmployeeList объекты в системы, которые все еще имеют старую версию EmployeeList класс. Для обеспечения совместимости со старыми и новыми версиями:

  • Определите OfficeNumber свойство как Hidden, но не Dependent.

  • Определите Location свойство как Dependent.

В этой версии EmployeeList класс, OfficeNumber свойство сохраняет значение, используемое Location собственность. При загрузке объекта присваиваются значения трех исходных свойств (Name, Email, и OfficeNumber), но не присваивает значение новому Location собственность. Отсутствие Location свойство в старом определении класса не является проблемой.

classdef EmployeeList
   properties
      Name
      Email
   end
   properties (Dependent)
      Location
   end
   properties (Hidden)
      OfficeNumber
   end
   methods
      function obj = set.Location(obj,val)
         obj.OfficeNumber = val;
      end
      function val = get.Location(obj)
         val = obj.OfficeNumber;
      end
   end
end

Обновить свойство при загрузке

Предположим, что класс изменяется таким образом, что значение свойства изменяется в его форме или типе. Ранее сохраненные объекты класса должны обновляться при загрузке, чтобы иметь соответствующее значение свойства.

Рассмотрим класс, который имеет AccountID собственность. Предположим, что все номера счетов должны быть перенесены из восьмизначных числовых значений в 12-элементные символьные массивы.

Вы можете учесть это изменение, внедрив loadobj способ.

loadobj способ:

  • Тесты, чтобы определить, load функция передала struct или объект. Все loadobj методы должны обрабатывать оба struct и объект при возникновении ошибки в load.

  • Тесты, чтобы определить, AccountID номер содержит восемь цифр. Если это так, измените его на 12-элементный символьный массив, вызвав paddAccID способ.

После обновления AccountID собственность, loadobj возвращает MyAccount объект, который MATLAB загружает в рабочую область.

classdef MyAccount
   properties
      AccountID
   end
   methods
      function obj = padAccID(obj)
         ac = obj.AccountID;
         acstr = num2str(ac);
         if length(acstr) < 12
            obj.AccountID = [acstr,repmat('0',1,12-length(acstr))];
         end
      end
   end
   methods (Static)
      function obj = loadobj(a)
         if isstruct(a)
            obj = MyAccount;
            obj.AccountID = a.AccountID;
            obj = padAccID(obj);
         elseif isa(a,'MyAccount')
            obj = padAccID(a);
         end
      end
   end
end

Вам не нужно реализовывать saveobj способ. Вы используете loadobj только для того, чтобы старые сохраненные объекты были обновлены во время загрузки.

Поддержка совместимых версий класса

PhoneBookEntry класс использует комбинацию методов для поддержания совместимости с новыми версиями класса.

Предположим, что вы определяете класс для представления записи в телефонной книге. PhoneBookEntry класс определяет три свойства: Name, Address, и PhoneNumber.

classdef PhoneBookEntry
   properties
      Name
      Address
      PhoneNumber
   end
end

Однако в будущих выпусках класс добавляет больше свойств. Для обеспечения гибкости, PhoneBookEntry сохраняет данные свойств в struct используя его saveobj способ.

methods
   function s = saveobj(obj)
      s.Name = obj.Name;
      s.Address = obj.Address;
      s.PhoneNumber = obj.PhoneNumber;
   end
end

loadobj метод создает PhoneBookEntry , который затем загружается в рабочую область.

methods (Static)
   function obj = loadobj(s)
      if isstruct(s)
         newObj = PhoneBookEntry;
         newObj.Name = s.Name;
         newObj.Address = s.Address;
         newObj.PhoneNumber = s.PhoneNumber;
         obj = newObj;
      else
         obj = s;
      end
   end
end

Версия 2 PhoneBookEntry Класс

В версии 2 PhoneBookEntry класс, вы разделяете Address свойство в StreetAddress, City, State, и ZipCode свойства.

Эти изменения не позволяют загрузить объект версии 2 в предыдущей версии. Однако в версии 2 используется несколько способов обеспечения совместимости:

  • Сохранить Address свойство (которое используется в версии 1) как Dependent собственность с частной SetAccess.

  • Определение Address метод получения свойства (get.Address) для построения char вектор, совместимый с версией 2 Address собственность.

  • saveobj метод вызывает get.Address метод назначения данных объекта struct совместим с предыдущими версиями. struct продолжает иметь только Address поле, созданное на основе данных в новом StreetAddress, City, State, и ZipCode свойства.

  • Когда loadobj метод устанавливает Address свойство вызывает метод набора свойств (set.Address), который извлекает подстроки, требуемые StreetAddress, City, State, и ZipCode свойства.

  • Transient (не сохранено) свойство SaveInOldFormat позволяет указать, следует ли сохранять объект версии 2 как struct или объект.

classdef PhoneBookEntry
   properties
      Name
      StreetAddress
      City
      State
      ZipCode
      PhoneNumber
   end
   properties (Constant)
      Sep = ', '
   end
   properties (Dependent, SetAccess=private)
      Address
   end
   properties (Transient)
      SaveInOldFormat = false;
   end
   methods (Static)
      function obj = loadobj(s)
         if isstruct(s)
            obj = PhoneBookEntry;
            obj.Name = s.Name;
            obj.Address = s.Address;
            obj.PhoneNumber = s.PhoneNumber;
         else
            obj = s;
         end
      end
   end
   methods
      function address = get.Address(obj)
         address = [obj.StreetAddress,obj.Sep,obj.City,obj.Sep,...
            obj.State,obj.Sep,obj.ZipCode];
      end
      function obj = set.Address(obj,address)
         addressItems = regexp(address,obj.Sep,'split');
         if length(addressItems) == 4
            obj.StreetAddress = addressItems{1};
            obj.City = addressItems{2};
            obj.State = addressItems{3};
            obj.ZipCode = addressItems{4};
         else
            error('PhoneBookEntry:InvalidAddressFormat', ...
               'Invalid address format.');
         end
      end
      function s = saveobj(obj)
         if obj.SaveInOldFormat
            s.Name = obj.Name;
            s.Address = obj.Address;
            s.PhoneNumber = obj.PhoneNumber;
         end
      end
   end
end

Связанные темы