Error while entering data in a class properties in matlab - matlab

I have made following class in matlab.
classdef details
% SCORES Summary of this class goes here
% Class for stroring the individual scores array of each of the
% comparison of the models and the test files including the number of
% coefficients used and number of gaussian
properties(SetAccess=public)
name;
rollno=0;
batch=0;
branch;
image;
end
methods
end
end
and i am accessing it in following way
detail=details;
detail.name=get(handles.edit2,'string');
detail.rollno=str2num(get(handles.edit3,'string'));
On running the program its giving following error:
??? No public field rollno exists for class details.
I don't know where is the error??????

I'm having the same problem as you, and I think I've found the cause. If you have a variable in the MATLAB workspace that is defined by the class, you cannot change it. That is, you probably have a test variable that is a "details" class, and was initialized before you added the "rollno" propriety. Try deleting any test variables.

Try changing this
properties(public)
to this
properties(SetAccess = public)
See the Matlab documentation for more info

Related

how to add courtesy copies in Matlab

I'd like to cc & bcc in matlab without any external components (File Ex has a solution that has a .jar file). Any references to do so?
As I thought, it involves Java, and it's not entirely straightforward, thanks to Matlab's love-hate relationship with Java.
Looking at ML's sendmail() function, the key line is:
msg.addRecipient(getRecipientTypeTo(msg), getInternetAddress(to{i}));
where getRecipientTypeTo() is a function to get a static class instance from Java for the recipient type:
function recipientTypeTo = getRecipientTypeTo(msg)
%getRecipientTypeTo Return the static RecipientType.TO.
% Get the class loader for the Message class.
cl = msg.getClass.getClassLoader;
% Returns a Class object pointing to RecipientType using that ClassLoader.
rt = java.lang.Class.forName('javax.mail.Message$RecipientType', false, cl);
% Returns a Field object pointint to TO.
field = rt.getField('TO');
% Gets the static instance of TO.
recipientTypeTo = field.get([]);
So, modify the static one is getting (CC and BCC are supported, entirely unsurprisingly), and use addRecipient().

Extending matlab classes: new methods for built-in classes

I inherited a complete toolbox, last revised in 2006, and I must update it to the latest version of Matlab. This toolbox defines some classes and defines methods for built in classes. More specifically, it creates some extra methods for objects of the control systems toolbox classes lti, ss, zpk and tf.
The first part, rebuilding the new classes, is already done. I am having troubles with the new methods for existing classes.
Since the code was written in an older version of Matlab, it uses class folders like #lti, #ss, #zpk to define the new methods. Now I need to keep the functionality, but using the new OOP model, in which not all #-folders are visible.
Does anybody know how to do that?
Since I had no luck trying to find a solution, I had to find one on my own. This is the method I came up with.
The toolbox had three new method for the zpk class. I created a new class, called sdzpk, and declared it to be a subclass of the built in zpk class. Then, wherever any of the new methods were used, I first converted the object to the new class before passing it to the method.
The following code may ilustrate that better:
Class definition file:
classdef sdzpk < zpk & sdlti
methods (Access = public)
function obj = sdzpk(varargin)
% Constructor method. Long code here to perform data validation
% and pass information to the zpk constructor
obj = obj#zpk(args{:});
end
% Existing methods
% This are the old files I inherited. No need to edit them.
tsys = ctranspose(sys);
sys = delay2z(sys);
sysr = minreal(sys,tol);
F = minreals(F,tol);
FP = setpoles(F,p);
F = symmetr(F,type,tol);
F = z2zeta(F,tol);
end
end
At several locations within the toolbox, the function minreals is called. All those calls were replaced with:
minreals(sdzpk(obj))
In that way, I make sure the new class is used and the correct method is applied.
I hope this helps somebody.

Why does my listener get deleted when I saveobj()?

Suppose I have two classes, a < matlab.mixin.Copyable and b < handle.
Here's a:
classdef a < matlab.mixin.Copyable
properties
hListener
end
methods
function obj = a(b)
obj.newListener(b);
end
function newListener(obj, b)
obj.hListener = addlistener(b, 'bEvent', #(o,e) disp('Received bEvent'));
end
function sobj = saveobj(obj)
sobj = copy(obj);
delete(sobj.hListener);
sobj.hListener = [];
end
end
end
and b:
classdef b < handle
events
bEvent
end
methods
function obj = b
end
function raiseEvent(obj)
notify(obj, 'bEvent');
end
end
end
I use saveobj in a to delete the listener upon save. I will manually re-instantiate a listener when I load the classes later.
a inherits from matlab.mixin.Copyable so I can do a copy during the saveobj operation - this way I can make a copy of the original object and change it, without affecting the original, and then save that to a MAT-file. (Supposedly - this is where my question is going.)
Now I run the following at the command line:
>> bob = b; alice = a(bob);
>> bob.raiseEvent
Received bEvent
Everything works. Now, let's save:
>> save ab alice bob
and try to raise the event again:
>> bob.raiseEvent
% NOTHING HAPPENS!
Turns out the listener is gone!
>> alice.hListener
handle to deleted listener
What is going on here? Why is the listener object shared between sobj and obj in the saveobj method?
In researching this question I discovered the answer. I figured I'd add to the body of knowledge around these parts.
Per the documentation for matlab.mixin.Copyable,
Given a call to the matlab.mixin.Copyable copy method of the form:
B = copy(A);
Under the following conditions, produces the described results:
A has dynamic properties — copy does not copy dynamic properties. You can implement dynamic-property copying in the subclass if needed.
A has no non-Dependent properties — copy creates a new object with no property values without calling the class constructor to avoid introducing side effects.
A contains deleted handles — copy creates deleted handles of the same class in the output array.
A has attached listeners — copy does not copy listeners. (emphasis added)
A contains objects of enumeration classes — Enumeration classes cannot subclass matlab.mixin.Copyable.
A delete method calls copy — copy creates a legitimate copy, obeying all the behaviors that apply in any other usage.
What I took this to mean originally was that a copy call would skip over a property whose value is a listener handle. Apparently what it means is that rather than skipping the property altogether, copy makes a reference to the original listener object, i.e., it copies the handle to the listener but not the listener itself.
Of course, when you load the copied object and it has that reference to listener, it'll complain:
Warning: Cannot load an object of class 'listener':
No matching constructor signature found.
Warning: During load:
An invalid default object has been detected while loading a heterogeneous array of
class event.listener. An empty array of class event.listener will be returned.
The easiest thing to do, then, is to modify saveobj:
function sobj = saveobj(obj)
sobj = copy(obj);
sobj.hListener = [];
end
Here, I don't explicitly call delete on the listener, as this would delete the actual object. Instead, I just clear the reference to that object.

Matlab oop - Clearing object from memory does not call 'delete' method as expected

Context
I created two similar PrimarySettings and SecondarySettings handle classes in matlab to store settings of my own and was willing to group both of them in a bigger AllSettings class for convenience.
All classes have a PropertyChanged event to monitor for settings modifications.
The code for all classes can be visualized from here.
Problem
When I test PrimarySettings and SecondarySettings classes to check if their are effectively calling their delete method when all instances are no longer referenced in the code I have no issue:
>> ps = PrimarySettings();
>> clear ps;
Destroying PrimarySettings.
>> ss = secondarySettings();
>> clear ss;
Destroying SecondarySettings.
The same when I test for proper event notifications:
>> as = AllSettings();
>> as.PrimarySettings.Titi = 12;
Property 'PrimarySettings.Titi' modified.
The problem is only with the AllSettings class for which delete method is never called at all:
>> as = AllSettings();
>> clear as;
!!!!!! here delete method is not called !!!!!
The object is still in memory while it is no longer referenced. This can be tested like this:
>> clear classes
Warning: Objects of 'SecondarySettings' class exist. Cannot clear this class or any of its superclasses.
Warning: Objects of 'PrimarySettings' class exist. Cannot clear this class or any of its superclasses.
Warning: Objects of 'AllSettings' class exist. Cannot clear this class or any of its superclasses.
Investigations
The problem seems linked to the way I am attaching the PropertyChanged event (the listener is probably still alive).
Unfortunately I truly don't understand why. Indeed, the code for attaching to events is very similar in all the classes I created.
PrimarySettings and SecondarySettings:
for idx = 1:propCount;
listener = addlistener(obj, meta.PropertyList(idx).Name, 'PostSet', #obj.onPropertyChanged);
listener.Recursive = true;
end
AllSettings:
for idx = 1:propCount;
propName = meta.PropertyList(idx).Name;
listener = addlistener(obj, propName, 'PostSet', #obj.onPropertyChanged);
listener.Recursive = true;
listener = addlistener(obj.(propName), 'PropertyChanged', #obj.onSubPropertyChanged);
listener.Recursive = true;
end
NB: If I comment the second listener (i.e. onSubPropertyChanged) then the AllSettings class works as expected!
Question
What's wrong with the deletion of AllSettings objects ?
If you need a specific diagnosis of the issue, I'm afraid you'll need to post more code, so we can trace through what's going on exactly.
But I would expect that the issue is that one of your listeners is storing a reference to another of your objects in a way that you're not expecting, so it's not getting destroyed when you call clear.
To help you diagnose things further, note that there are two ways to create listeners:
Using addlistener, which ties the listener's lifecycle to the object that is the source of the event.
Constructing the listener directly using event.listener, where the listener exists only while it is in scope, and is not tied to the event-generating object's existence.
For more information, see the section "Ways to create listeners" in this documentation page on Events and Listeners — Syntax and Techniques.
Hope that helps!

Preventing serialisation

I have a Matlab class where implementing serialisation and deserialisation would be painful, and not needed.
Therefore, I have overloaded saveobj as follows:
function sobj = saveobj(self)
sojb = [];
error(['atmlab:' mfilename ':nostoring'], ...
['You tried to store %s %s. Loading is impossible, ' ...
'therefore I refuse to store. Sorry.'], ...
class(self), self.name);
end
Unfortunately, when I test this, Matlab tries to be helpful and turns the warning into an error (twice for some reason):
>> save('/tmp/test.mat', 'X')
Warning: While saving an object of class 'SatDataset':
You tried to store SatDataset amsua. Loading is impossible, therefore I refuse to store. Sorry.
(Type "warning off atmlab:SatDataset:nostoring" to suppress this warning.)
Warning: While saving an object of class 'SatDataset':
You tried to store SatDataset amsua. Loading is impossible, therefore I refuse to store. Sorry.
(Type "warning off atmlab:SatDataset:nostoring" to suppress this warning.)
I can turn the warning into an error using an undocumented feature:
>> warning error atmlab:SatDataset:nostoring
>> save('/tmp/test.mat', 'X')
Error using save
While saving an object of class 'SatDataset':
You tried to store SatDataset amsua. Loading is impossible, therefore I refuse to store. Sorry.
Unexpected error status flag encountered. Resetting to proper state.
But this is not satisfactory, as I don't want to rely on undocumented features and I certainly don't want to force users to do so.
How can I effectively throw an error, prevent users from trying to serialise objects from my class?
By request, a minimum example to reproduce the situation:
% in TestClass.m
classdef TestClass < handle
methods
function sobj = saveobj(self)
sojb = [];
error('Unable to store %s objects', class(self));
end
end
end
% on the interactive prompt:
>> t = TestClass();
>> save('/tmp/fubar.mat', 't');
Warning: While saving an object of class 'TestClass':
Unable to store TestClass objects
Warning: While saving an object of class 'TestClass':
Unable to store TestClass objects
Personally, I prefer to mark all properties as Transient, and let the object effectively have an invalid state that is the result of saving/loading. It's remarkably hard to prevent MATLAB from saving your data, and your workaround might significantly interfere with your users' workflow.
Your code actually throws the error, you should replace your call of error() by warning()