Main Content

Code Patterns for saveobj and loadobj

The recommended process for customizing serialization and deserialization of objects is to use the matlab.mixin.CustomElementSerialization mixin (since R2024b) and its associated classes to control how objects are serialized and deserialized. However, using the mixin does not work if:

  • You have an existing implementation of saveobj that serializes data in a type other than an object or a struct, and your loadobj implementation can only deserialize data from that particular type.

  • You are using a MATLAB® release older than R2024b.

Using saveobj and loadobj

Depending on the requirements of your class, there are various ways you can use saveobj and loadobj methods. This pattern is a flexible way to solve problems that you cannot address by simpler means.

The basic process is:

  • Use saveobj to save all essential data in a struct.

  • Use loadobj to reconstruct the object from the saved data.

This approach is not useful in cases where you cannot save property values in a struct field, such as a file identifier.

If you implement a saveobj method without implementing a loadobj method, MATLAB loads a default object of the class using the current class definition. Add a loadobj method to the class to create an object using the data saved with the saveobj method.

Use saveobj to Store Class Data as a Structure

Define saveobj as an ordinary method that accepts an object of the class and returns a struct.

  • Copy each property value to a structure field of the same name.

  • You can save only the data that is necessary to rebuild the object. Avoid saving whole object hierarchies, such as those created by graphs.

methods
   function s = saveobj(obj)
      s.Prop1 = obj.Prop1;
      s.Prop2 = obj.Prop2
      s.Data = obj.GraphHandle.YData;
   end
end
end

Use loadobj to Load Class Data from a Structure

Define loadobj as a static method. Create an object by calling the class constructor. Then assign values to properties from the struct passed to loadobj. Use the data to regenerate properties that were not saved.

methods(Static)
   function obj = loadobj(s)
      if isstruct(s)
         newObj = ClassConstructor; 
         newObj.Prop1 = s.Prop1;
         newObj.Prop2 = s.Prop2
         newObj.GraphHandle = plot(s.Data);
         obj = newObj;
      else
         obj = s;
      end
   end
end

If the load function encounters an error, load passes loadobj a struct instead of an object. Your loadobj method must always be able to handle a struct as the input argument. The input to loadobj is always a scalar.

Using loadobj Without a Corresponding saveobj

loadobj can handle a struct input even if you are not using a saveobj method. For example, the GraphExpression class creates a graph of a MATLAB expression over a specified range of data. GraphExpression uses its loadobj method to regenerate the graph, which is not saved with the object.

classdef GraphExpression
   properties
      FuncHandle
      Range
   end
   methods
      function obj = GraphExpression(fh,rg)
         obj.FuncHandle = fh;
         obj.Range = rg;
         makeGraph(obj)
      end
      function makeGraph(obj)
         rg = obj.Range;
         x = min(rg):max(rg);
         data = obj.FuncHandle(x);
         plot(data)
      end
   end
   methods (Static)
      function obj = loadobj(s)
         if isstruct(s)
            fh = s.FuncHandle;
            rg = s.Range;
            obj = GraphExpression(fh,rg);
         else
            makeGraph(s);
            obj = s;
         end
      end
   end
end

Create a GraphExpression instance with an anonymous function and a range of data as inputs.

h = GraphExpression(@(x)x.^4,[1:25])
h = 

  GraphExpression with properties:

    FuncHandle: @(x)x.^4
         Range: [1x25 double]

Save the GraphExpression object and close the graph.

save myFile h
close

When you load the object, MATLAB recreates the graph.

saveobj and loadobj with Subclass Objects

If the most specific class of an object does not define a loadobj or saveobj method, the class can inherit loadobj or saveobj methods from a superclass.

If any class in the hierarchy defines saveobj or loadobj methods:

  • Define saveobj for all classes in the hierarchy.

  • Call superclass saveobj methods from the subclass saveobj method because the save function calls only the most specific saveobj method.

  • The subclass loadobj method can call the superclass loadobj, or other methods as required, to assign values to their properties.

Reconstruct the Subclass Object from a Saved struct

Suppose that you want to save a subclass object by first converting its property data to a struct in the subclass saveobj method. Then you reconstruct the object when loaded using its loadobj method. This action requires that:

  • Superclasses implement saveobj methods to save their property data in the struct.

  • The subclass saveobj method calls each superclass saveobj method and returns the completed struct to the save function. Then the save function writes the struct to the MAT-file.

  • The subclass loadobj method creates a subclass object and calls superclass methods to assign their property values in the subclass object.

  • The subclass loadobj method returns the reconstructed object to the load function, which loads the object into the workspace.

The following superclass (MySuper) and subclass (MySub) definitions show how to code these methods.

  • The MySuper class defines a loadobj method to enable an object of this class to be loaded directly.

  • The subclass loadobj method calls a method named reload after it constructs the subclass object.

  • reload first calls the superclass reload method to assign superclass property values and then assigns the subclass property value.

classdef MySuper
   properties
      X
      Y
   end
   methods
      function S = saveobj(obj)
         S.PointX = obj.X;
         S.PointY = obj.Y;
      end
      function obj = reload(obj,S)
         obj.X = S.PointX;
         obj.Y = S.PointY;
      end
   end
   methods (Static)
      function obj = loadobj(S)
         if isstruct(S)
            obj = MySuper;
            obj = reload(obj,S);
         end
      end
   end
end

Call the superclass saveobj and loadobj methods from the subclass saveobj and loadobj methods. (The loadobj method does this indirectly by calling the reload method, which in turn calls the superclass loadobj.)

classdef MySub < MySuper
   properties
      Z
   end
   methods
      function S = saveobj(obj)
         S = saveobj@MySuper(obj);
         S.PointZ = obj.Z;
      end
      function obj = reload(obj,S)
         obj = reload@MySuper(obj,S);
         obj.Z = S.PointZ;
      end
   end
   methods (Static)
      function obj = loadobj(S)
         if isstruct(S)
            obj = MySub;
            obj = reload(obj,S);
         end
      end
   end
end

Additional Considerations for loadobj and saveobj

When you decide to modify the default save and load process with loadobj and saveobj, keep these points in mind:

  • If loading any property value from the MAT file produces an error, load passes a struct to loadobj. The struct field names correspond to the property names extracted from the file.

  • loadobj must always be able to accept a struct as input and return an object, even if saveobj is not defined or saveobj does not return a struct.

  • If saveobj returns a struct, then load always passes that struct to loadobj.

  • Subclass objects inherit superclass loadobj and saveobj methods. Therefore, if you do not implement a loadobj or saveobj method in the subclass, MATLAB calls the inherited methods.

    If a superclass implements a loadobj or saveobj method, then a subclass can also implement a loadobj or saveobj method that calls the superclass methods. For more information, see Call Superclass Methods on Subclass Objects.

  • The load function does not call the constructor by default. For more information, see Default Save and Load Process for Objects.

  • Customizing loadobj and saveobj is not supported for enum classes.

Related Topics