MATLAB Answers

Custom Object property save/load problem

11 views (last 30 days)
Roger Pierson
Roger Pierson on 11 Apr 2020
Commented: TADA on 11 Apr 2020
Greetings. I have run up against the most infurating problem. I obviously broke something with a recent change, but I can't see how I possibly could have. Hopefully one of you detectives can help.
I have a custom class I'll just call classDataSet here for simplicity. classDataSet holds data in a property called dataSet as a table, and holds notes about that data in another property called dataSetNotes. This morning I made a change to how I was setting the dataSetNotes property. Originally I passed a 3 column table of notes to the set property method, did some validation to make sure it met expectations, and then set the property to that table.
The change I made started with writting another class (classLogBook) that deals with the administrative work of adding and working with notes. Now when I want to set the dataSetNotes property of classDataSet, I pass classLogBook to the set property method for dataSetNotes. This method just pulls a struct from classLogBook, converts it to table and saves it to the dataSetNotes property. Seems to me like barely any change at all. The end result is that the dataSetNotes property is still a three column table, regardless of how it is being set.
An all this works fine. Notes are visible in classDataSet after I set the property. There is no abnormal indication at all. UNTIL I trie to save classDataSet to a .mat file and load it again. After loading from file, the dataSetNotes property is empty. I dont' know if it isn't saving or it isn't loading. And I'm at a loss how to troubleshoot.
Here is the property set code
%% Property Set: dataSetNotes
function obj = set.dataSetNotes(obj,logBookObject)
% Accepts an object of classAvengerLogBook type and extracts the logbook.
if class(logBookObject) == "classLogBook"
logBookStruct = logBookObject.logBookStruct;
logBookTable = struct2table(logBookStruct);
obj.dataSetNotes = logBookTable;
else
error("dataSetNotes property requires the passed argument to be an object of type classLogBook")
end
end
I can't imagine how it could be related, but here is the class constructor for the classLogBook object. The only interaction these two classes have is when classLogBook is passed to classDataSet to create a table that gets assigned to dataSetNotes (...which is the property that no longer save/loads).
%% Class Constructor
function obj = classLogBook(logTitle)
% Sets a default title if the user does not pass one.
obj.logBookStruct(1).time = UTC_Now;
obj.logBookStruct(1).author = "Logbook Constructor";
if nargin == 1
obj.logBookStruct(1).entry = logTitle;
else
obj.logBookStruct(1).entry = "Title not Set";
end
end
I appreciate any help you can give. Even if it is just an approach to troubleshooting what is going on.

  0 Comments

Sign in to comment.

Accepted Answer

TADA
TADA on 11 Apr 2020
It seems to me that you are saving a 3 column table to the .mat file, then when you load it again, it uses the property to set it again, but now thats not an instance of classLogBook, so you get a nifty exception that load function hides from you (that is annoying)
The easiest solution in my mind would be to add another validation for a table:
function obj = set.dataSetNotes(obj,logBookObject)
if istable(logBookObject)
% do the old validation you used to perform
obj.dataSetNotes = logBookObject
elseif class(logBookObject) == "classLogBook"
% Accepts an object of classAvengerLogBook type and extracts the logbook.
logBookStruct = logBookObject.logBookStruct;
logBookTable = struct2table(logBookStruct);
obj.dataSetNotes = logBookTable;
else
error("dataSetNotes property requires the passed argument to be an object of type classLogBook")
end
end

  3 Comments

TADA
TADA on 11 Apr 2020
I was curious, so I checked....
It does save your value, and it fails when loading again due to the exception
To check I generated two classes:
classdef class1
properties
a;
end
methods
function this = set.a(this,inputArg)
this.a = inputArg.text;
end
end
end
classdef class2
properties
text char;
end
end
next, generate objects:
obj1 = class1()
obj1 =
class1 with properties:
a: []
obj2 = class2()
obj2 =
class2 with properties:
text: ''
obj2.text = 'abc'
obj2 =
class2 with properties:
text: 'abc'
obj1.a = obj2
obj1 =
class1 with properties:
a: 'abc'
So far so good.
Now save and load it and you get:
obj1
obj1 =
class1 with properties:
a: []
Add the fix:
classdef class1
properties
a;
end
methods
function this = set.a(this,inputArg)
if ischar(inputArg)
this.a = inputArg;
else
this.a = inputArg.text;
end
end
end
end
now, reload the object previously saved:
obj1
obj1 =
class1 with properties:
a: 'abc'
Roger Pierson
Roger Pierson on 11 Apr 2020
TADA indeed. That was exactly the problem and the solution. Thank you so much! My next idea was to start throwing hardware around in a rage to see if that would help, but now I don't have to. :)
TADA
TADA on 11 Apr 2020
throwing hardware around is usually my first urge, and its pretty hard to resist :)

Sign in to comment.

More Answers (1)

Matt J
Matt J on 11 Apr 2020
Edited: Matt J on 11 Apr 2020
I dont' know if it isn't saving or it isn't loading. And I'm at a loss how to troubleshoot.
Put a breakpoint on this line,
if class(logBookObject) == "classLogBook"
Then, save and reload the object from the .mat file. Is the breakpoint reached (and debug mode trigerred) when you do so? If so, does it happen during save or during load?

  1 Comment

Roger Pierson
Roger Pierson on 11 Apr 2020
Good thought, thanks.
TADA has solved the mystery though.

Sign in to comment.


Translated by