Variable YYY originally saved as a XXX cannot be instantiated as an object and will be read in as a uint32 - matlab

I've made a mistake and recorded a bunch of important data using a class definition that I can't find anymore. The methods are not important, I just want the data; a struct conversion would be fine.
Is there any way I can recover this?
Googling it did not help.

The solution is to create a new class that overloads the loadobj method. See here for more information regarding the load process for classes.
I replicated your problem by creating a class:
classdef myclass
properties
Prop1
Prop2
Prop3
end
methods
function obj = myclass(a,b,c)
obj.Prop1 = a;
obj.Prop2 = b;
obj.Prop3 = c;
end
end
end
Then I created an object of this class and saving it to a file "x.mat":
x = myclass('a',56,[1,2,3]);
save x
Next, I deleted the myclass file and did clear classes. This put me in your situation.
I then created a new myclass class that overloads the loadobj method:
classdef myclass
properties
data
end
methods (Static)
function obj = loadobj(s)
obj = myclass;
obj.data = s;
end
end
end
Note how it doesn't know any of the original properties. This does not matter. If any of the original properties is missing when loading an object from a MAT-file, loadobj will be called with s being a struct containing all the properties of the original object.
With this new class definition, load x created an object x of class myclass, where x.data was a struct containing the properties of the object saved in "x.mat".

Related

How do I use static factory method in matlab package?

I have following class definition under +mypackage\MyClass.m
classdef MyClass
properties
num
end
methods (Static)
function obj = with_five()
obj = MyClass(5);
end
end
methods
function obj = MyClass(num)
obj.num = num;
end
end
end
I use with_five() as a static factory method.
Following script should create two objects.
import mypackage.MyClass
class_test1 = MyClass(5);
class_test2 = MyClass.with_five();
class_test1 has been created.
For class_test2 it says:
Error using MyClass.with_five
Method 'with_five' is not defined for class 'MyClass' or is removed from MATLAB's search path.
Error in Testpackage (line 4)
class_test2 = MyClass.with_five();
When I put MyClass.m outside of a package folder and remove the "import" statement, it works.
What am I doing wrong?
There are several wonky things in MATLAB with packages and with static methods.
First, functions within a package must use the package name to reference other functions or classes within the same package (see here). So the static method mypackage.MyClass.with_five() must be declared as follows:
methods (Static)
function obj = with_five()
obj = mypackage.MyClass(5);
end
end
Without this, I see:
>> mypackage.MyClass.with_five
Undefined function or variable 'MyClass'.
Error in mypackage.MyClass.with_five (line 8)
obj = MyClass(5);
Second, static class methods (at least the ones for classes inside packages) are not loaded until an object of the class is created. So we need to call the class constructor first:
>> clear classes
>> mypackage.MyClass.with_five
Undefined variable "mypackage" or class "mypackage.MyClass.with_five".
>> mypackage.MyClass(1);
>> mypackage.MyClass.with_five
ans =
MyClass with properties:
num: 5
The same is true if we import the class:
>> clear classes
>> import mypackage.MyClass
>> MyClass.with_five
Undefined variable "mypackage" or class "mypackage.MyClass.with_five".
>> MyClass(3);
>> MyClass.with_five
ans =
MyClass with properties:
num: 5
This second point was true in R2017a (where the outputs above were generated), but is no longer true in R2021a. I don't know in which release of MATLAB this was fixed, but in R2021a it is no longer necessary to create an object of a class to use its static method.
I think what you are missing is the fact that when you import a static method, you have to import the class name and the method name (https://au.mathworks.com/help/matlab/matlab_oop/importing-classes.html)
This works:
classdef MyClass
properties
num
end
methods (Static)
function obj = with_five()
obj = MyClass(5);
end
end
methods
function obj = MyClass(num)
obj.num = num;
end
end
end
Then do the following:
>> import MyClass.with_five
>> x = with_five
Output:
x =
MyClass with properties:
num: 5
That being said: don't create an object in a member function of its own class! As you suggest, a better choice is to move the factory to a different class. If you wanted to make a bunch of chainsaws, you would never go about trying to design a chainsaw that has a button on it that builds chainsaws. You would rather design a factory that can produce chainsaws that are designed to cut down trees.
A 'static factory' is not a bad thing. This is actually a pretty common pattern especially in C#. However, the factory is always its own class. Calling that method from another object that inherits from or extends that class (which I'm not sure you can even do in Matlab...) would most certainly be confusing if not deadly. I also can't think of any reason you would ever need to do this. In fact I don't understand why with_five() should be static at all

Force conversion of struct to object in MATLAB loadobj function

I am working with a custom defined class I called "PathObj_Standard". I want to make sure that when I load this class, if the property CalcDate was saved as a cell array it is converted to a standard array. However, I changed the class definition some time ago, so when I use the loadobj function, I am getting a struct instead of an object. The original code I'm using has a lot more properties, so I'd rather not create a new object by assigning property by property from the struct to a new object. Furthermore, I'm also hesitant to change the constructor to accept a struct as an argument.
I tried using the class function inside loadobj, but I am getting a Cannot redefine class 'PathObj_Standard' without a call to 'clear classes' error. Isn't this function supposed to force conversion of a struct to an object? Why doesn't it work within the loadobj function?
classdef PathObj_Standard < handle
properties (SetAccess = protected)
CalcDate;
Name;
end
methods(Static)
function obj=loadobj(s)
if isstruct(s)
obj=class(s,'PathObj_Standard');
else
obj=s;
end
if not(isempty(obj.CalcDate)) && iscell(obj.CalcDate)
obj.CalcDate=cell2mat(obj.CalcDate);
end
end
end
methods
function obj=PathObj_Standard(Name,CalcDate)
obj.Name=Name;
obj.CalcDate=CalcDate;
end
end
The issue is that calling class attempts to create a class which you can't do from within your loadobj. You'll want to call the actual constructor
Also in my experience, the easiest way to construct a class from a struct is to inherit from hgsetget rather than handle as that automatically has the set and get methods of MATLAB's graphics objects and these methods can accept property/values in the form of a struct. In newer versions of MATLAB, you can also use the SetGet mixin
classdef PathObj_Standard < hgsetget
If you do this, you could change your loadobj method to be something like
function obj = loadobj(s)
% Update the input struct as needed
if isfield(s, 'CalcDate') && ~isempty(s.CalcDate) && iscell(s.CalcDate)
s.CalcDate = cell2mat(s.CalcDate);
end
% Call the default constructor
obj = PathObj_Standard();
% Update all properties that were supplied to loadobj
set(obj, s)
end

Access data in subclass from superclass

I have an object from my own class object that inherits from my own class data and my own class graphic in MATLAB. To represent the object object, it uses properties and methods from the data-superclass. Now I want to draw my object object with methods from the graphic-superclass, but the methods in this superclass don't know anything about its object-subclass.
Is there a way to give the required data, that is stored in the object-subclass, to the graphic-superclass without putting this information into a function argument like object.draw(this_data_stuff) with the method drawfrom the graphic-superclass and the data this_data_stuff from the object-subclass?
The only way I figured out is to store the subclass object object as property in the graphic-superclass, but it seems odd to store a subclass-object as property in a superclass-object, while the subclass inherits from the same superclass.
EDIT:
data-class:
classdef data < handle
properties
data_stuff
end
methods
function obj = data
end
function obj = compute(obj)
obj.data_stuff = ... % math
end
end
end
graphic-class:
classdef graphic < handle
properties
end
methods
function obj = graphic
end
function obj = draw(obj)
plot(obj.data_stuff,t) % ERROR, property 'data_stuff' is unknown
end
end
end
object-class:
classdef object < data & graphic
properties
end
methods
function obj = object
end
end
end
Test:
object_A = object; % creates object
object_A.compute; % generates data_stuff
object_A.draw; % draws data_stuff, Error here, because 'draw` needs access to the 'data_stuff'-property.

Define method in a separate file with attributes in MATLAB

As you know we can define class definition and method definition in separate files in #folder. How we can do that if we have attributes for method? I read in MATLAB OOP documentation that we should use this structure in method file:
classdef myClass
method (att = value,...)
tdata = testdata(obj,arg1,arg2)
end
end
But we have another file (myClass) in this folder for class definition so if we have this structure we have two class definition files. one of them has properties definition and another has methods properties (two files with same name!). If we change above classdef name(myClass) to function name(testdata), we have a error in MATLAB. What should I do?
If you're defining your class using an #-folder and separate files, you don't need two class definition files. You need a single class definition file (which is basically as you've defined in your question) and a separate file that contains just your method, implemented as a function.
For example:
#MyClass\MyClass.m
classdef MyClass
properties (GetAccess = public, SetAccess = private)
myGreeting
end
methods (Access = public)
function obj = MyClass
obj.myGreeting= 'hello'
end
function sayhello(obj, name)
txt = obj.getText(name);
disp(txt)
end
end
methods (Access = private)
txt = getText(obj, name)
end
end
#MyClass\getText.m
function txt = getText(obj, name)
txt = [obj.myGreeting, ' ', name];
end
Note that you only need to include the stub definition of the method within the class definition file if you need to modify the method attributes from default. If it's a public method (and non-Static, non-Hidden, non-Sealed, non-Abstract etc), you don't need to include it at all, you just need to include the file in the #-folder.

MatLab OOP Setting a Property via a Utility Method

I'm trying to change a property in a class called houses via a utility method which is Static. I'm getting terribly confused with the reference obj as I don't know when and where it should be used. I am trying to bypass the constructor method so I can access the setProperty method, but I am getting errors such as too many output arguments. I've tried passing in obj as well as x, but I get similar errors. However, I can change the property a if I pass in a value to the constructor method.
classdef houses
properties
a;
end
methods
% constructor method
function obj = houses()
end
end
methods (Static)
function setProperty(x)
obj.a = x;
end
end
end
In general, you should not use static methods to set properties of a class. If your property is public, then you can use a static method but it is highly recommended that you do not. If your property is private/protected, then you definitely cannot use a static method to modify it.
Your class should look like this then (I took the liberty of stating explicitly the access properties of each block):
classdef houses
properties (Access = private)
a;
end
methods (Access = public)
% constructor method
function obj = houses()
end
function SetA(obj, a)
obj.a = a;
end
function DoSomething(obj, more_parameters)
% Lengthy stuff here
end
end
end
Now, regarding your question about obj: the answer is you must pass obj as the first argument of every instance method. The variable obj refers to the current instance of the class in a generic way. See for example the method DoSomething.
Static methods do not have access to any of the properties of the class, unless public. As such, when declaring a static method, you should not pass the obj variable.
Last thing: always use explicit access modifiers for your properties and methods. It will save you some headaches.
A static method is not typically supposed to access an object (hence it does not have access to obj).
If you want to modify a static propperty (shared by all objects, and the class itself), you can use something like:
classdef houses
properties (Static)
a;
end
methods
% constructor method
function obj = houses()
end
end
methods (Static)
function setProperty(x)
houses.a = x;
end
end
end
Regarding obj, it is the 1st argument of every methods (non static). So when you do:
o = myClass();
o.myMethod(args);
Matlab will see this as:
myMethod(o, args);
So when you define the method, you have to put obj as the 1st argument (in fact you can choose any name, it does not have to be obj).