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

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

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

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

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

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

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

  • Создайте свойство, получают метод для OfficeNumber это возвращает значение 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

Похожие темы