2
votes

I have a classe derived from matlab.mixin.Copyable. Some of the properties have set methods. I want the setting of those properties to also update other properties so that the relationship between the parameters are consistent (a classic use of set methods).

Unfortunately, when I load a *.mat file [specifically using, say, x=load('file.mat')], setters are also used. There should be no need for that kind of automatic update of multiple parameters, since all the object's properties can be copied from the *.mat file and self-consistency is automatically maintained. Instead, using setters during load causes errors because the setter uses other properties that haven't yet been assigned to in the load process. I see this from error that occurs during the load, and from checking the properties that are needed by the setter.

Is there any way to force the load to do a simple replication of the property values contained the *.mat file? Some of the properties are complex objects themselves, so what's needed is a recursive copy-by-value during load. It seems rather inappropriate to use setters during a load, for the reasons above.

P.S. I say above that the setter uses another as-yet-unassigned property. Let's call this property p2. It also gets assigned to by a setter for 3rd property s1. It seemed odd, but s1 does have a value, while p2 does not. One possible reason is that p2 relies on other properties in addition to s1, and those might not have been assigned to when s1 is loaded (i.e., when the s1 setter is invoked). The whole problem stems from the fact that load occurs outside of the context and the order in which properties are assigned to during the execution of the code that created it. This is the key reason why (it seems to me that) load should not use setters. Otherwise, it seems to be incompatible with either copying or loading (I'm not sure which at the moment -- maybe both).

1

1 Answers

4
votes

The process MATLAB uses to load objects is well documented. This page mentions, among many other things, that the set methods are called to prevent issues that happen when a class definition changes, and you try to load an object from that class from an old file.

There is also a page explaining how to modify the save and load process. This page describes the use of loadobj, defined as a static method to your class, to change how the object is constructed from the information in the file. loadobj is called when one of the set methods throws an error; but it is always called if saveobj returns a struct. That is, one solution to your problem is to have saveobj create a struct with all the data, and have loadobj reconstruct your object from that struct.

This other documentation page describes how to design your class to avoid property initialization order dependency -- which is the problem you describe having. The way to do this is to have all public properties be dependent properties, with the "actual" data properties being hidden and not interdependent. You might be able to construct your class this way, for example with a single data property (a cell array or struct), which would be loaded and saved in one go, and the public properties simply using a portion of this cell or struct in the set and get methods.