Saving and Loading Objects

Modifying the Save and Load Process

You can save objects to a MAT-file and then reload them into the workspace. In most cases, saving and loading objects from MAT-files is no different from working with other variables. However, you can modify the save and load process to better support class backward and forward compatibility.

Class saveobj and loadobj Methods

You can define methods for your class that are executed when you call save or load on an object:

If you implement a saveobj method that modifies the object being saved, then you probably need to implement a loadobj method to return the object to its proper state when reloading it. For example, you might want to store an object's data in a struct array and reconstruct the object when reloaded to guard against the possibility that the class definition might change.

What Information Is Saved

Saving objects in MAT-files saves the following data:

Even if your saveobj method saves only the object's data in an array and not the object itself, the object's class name is saved so that load can determine which loadobj method to call.

How Property Data is Loaded

If the class's ConstructOnLoad attribute is set to true, then the load process calls the class constructor with no arguments and creates a new object of the class using the data stored in the saved object. When loading objects from MAT-files the load function does the following:

It is possible for an initial value to cause an error in a set property method (for example, the class definition might have changed). When an error occurs while an object is being loaded from a file, the MATLAB runtime returns the saved values in a MATLAB struct.

When an error occurs, your loadobj method is passed the struct instead of an object. The loadobj method must use the values in the struct to call the class constructor and create a new object.

You Must Implement loadobj as a Static Method

You must implement the loadobj method as a static method because loadobj can actually be called with a struct or other data instead of an object of the class. The saveobj method is implemented as an ordinary method (i.e., calling it requires an instance of the class).

Code for These Examples

The following discussion on saving and loading objects refers to a BankAccount class. Use the following link to see the full code for this class.

Open in editor

Processing Objects During Load Operations

When you load an object that has been saved to a MAT-file using the load function, the object's loadobj method is called, if it exists. Implementing a loadobj method enables you to apply some processing to the object before it is loaded into the workspace. This might be necessary in cases such as the following:

Updating an Object Property When Loading with loadboj

In the following example, the loadobj method checks to see if the object to be loaded has an old, shorter account number and calls a function to return an updated account number if necessary. After updating the object's AccountNumber property, loadobj returns the object to be loaded into the workspace.

methods (Static = true)
   function obj = loadobj(a)
      accnb = a.AccountNumber;
      if length(num2str(accnb)) < 12
         a.AccountNumber = updateAccountNumber(accnb); % update object
      end
      obj = a;  % return the updated object
   end
end

In this case, you do not need to implement a saveobj method and are using loadobj only to ensure older saved objects are brought up to date before loading.

The next section provides an example in which loadobj performs specific operations to recreate an object based on the data returned by saveobj during the save operation.

Processing Objects During Save and Load Operations

Suppose that you know class definitions are likely to change over time, but you want to be able to reload older data and create objects according to the most current class definition. One approach is to save the object's data in a struct, but not the object itself.

To use this approach, create a saveobj method to extract the data you want to save from the object and write this data into a struct, which saveobj returns to the save function. You must also implement a loadobj method to extract the data from the reloaded variable and use this data to create a new object.

Saving Object Data Only with saveobj

The following example saves the data from a BankAccount object having two properties. saveobj saves the values of the AccountNumber and the AccountBalance properties in the struct variable A, which has field names that match the property names. saveobj then returns the variable A to be saved in the MAT-file by the save function.

methods 
   function A = saveobj(obj)
      A.AccountNumber = obj.AccountNumber;
      A.AccountBalance = obj.AccountBalance;
   end
end

Reconstructing Objects with loadobj

Suppose that a new property is added to the BankAccount class and all saved BankAccount objects must be recreated using the new class constructor. To create a valid object, call the constructor using the data saved in the variable A and pass any other arguments required. Because you are calling the latest version of the constructor in the loadobj method, the very latest version of the objects is created.

In this example, a new property called AccountStatus was added to the BankAccount class. If the account balance is greater than zero, AccountStatus is set to open. If the account balance is zero or less, AccountStatus is set to overdrawnor to frozen.

This loadobj method calls the class constructor with the appropriate value for the new property after testing the data saved from the AccountBalance property.

methods (Static = true)
   function obj = loadobj(a)
      if A.AccountBalance > 0
         obj = BankAccount(a.AccountNumber,a.AccountBalance,'open');
      else
         obj = BankAccount(a.AccountNumber,a.AccountBalance,'overdrawn');
      end
   end
end

saveobj Method Expanded

Using saveobj and loadobj to manage changes to class definitions probably requires you to update these methods with each modification to the class. For example, you might need to accommodate a mix of old and new BankAccount objects with the saveobj method.

methods 
   function A = saveobj(obj)
      A.AccountNumber = obj.AccountNumber;
      A.AccountBalance = obj.AccountBalance
      if BankAccount.isPropertyOf(obj,'AccountStatus')
         A.AccountStatus = obj.AccountStatus;
      end
   end
end

Does an Object Have a Particular Property

This class defines a static method that determines if a property exists for an object. isPropertyOf is used to determine if the object being loaded has the new AccountStatus property.

methods (Static = true)
   function tf = isaPropertyOf(anyobj,PropName)
      if ~isa(anyobj,'meta.class')
         mobj = metaclass(anyobj);
      else
         mobj = anyobj;
      end
      tf = false;
      for k=1:length(mobj.Properties)
         if strcmp(mobj.Properties{k}.Name,PropName)
            tf = true;
         end
      end
   end
end

Note that you can also use this method to determine if a class defines a particular property without creating an instance. For example, this statement determines if the BankAccount class defines a property called AccountType:

BankAccount.isaPropertyOf(?BankAccount,'AccountType')

The ?BankAccount argument creates a meta.class object from the class name, and then checks the class definition to determine if the class currently defines the named property.

See Obtaining Information About Classes with Meta-Classes for more information on meta-class objects.

  


 © 1984-2008- The MathWorks, Inc.    -   Site Help   -   Patents   -   Trademarks   -   Privacy Policy   -   Preventing Piracy   -   RSS