I want to set up an object of a class, which contians all variables for a simulink model as its properties.
To later be able to use parallel simulations, I want to have a function in the methods, which takes all the properties and feeds them to a Simulink SimulationInput Object (via the 'setVariable' method),
but the setVariable-function does not fill up the variables of the object 'in' when I run it.
The code looks somewhat like this:
classdef SimSetup
properties
mdl = 'SimulinkFile'
SimulationTime = 2
Plant
in
end
methods
function this = SimSetup()
open_system(this.mdl);
this.Plant = load('PlantData.mat','xPlant');
end
function createSimIn(this)
this.in = Simulink.SimulationInput(this.mdl);
this.in = this.in.setVariable('SimulationTime', this.SimulationTime);
end
end
Thanks in advance
The mistake was the following:
I either had to use a handle class or had to return the output of the function to the object itself (in short: function this = createSimIn(this)).
Related
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
In MATLAB, one of the attributes of a class (defined after classdef) is Sealed, which means that no class can use it as a superclass (or to be more precise, "to indicate that these classes have not been designed to support subclasses."1).
For example, if I try to instantiate a class that's defined as below (considering table is Sealed):
classdef SomeLie < table
end
I would get the 'MATLAB:class:sealed' error:
>> A = SomeLie;
Error using SomeLie
Class 'table' is Sealed and may not be used as a superclass.
As I refuse to be told by a machine what I may or may not do, I would like to subclass a Sealed class, regardless. How can I do that in MATLAB R2017a?
I'm having a hard time believing that this system is completely airtight, so I'm looking for a solution that would cause the Sealed attribute to be silently ignored (or something of that sort). The desired solution should work without modifying any "library class definitions" to remove Sealed from them.
I tried playing around with "reflection", but arrived at a dead end...
classdef SomeLie % < table
properties (Access = private)
innerTable table;
end
properties (GetAccess = public)
methodHandles struct = struct();
end
methods
function slObj = SomeLie(varargin)
slObj.innerTable = table(varargin{:});
% methodHandles = methods(slObj.innerTable);
ml = ?table; ml = {ml.MethodList.Name}.';
ml = setdiff(ml,'end');
tmpStruct = struct;
for indM = 1:numel(ml)
tmpStruct.(ml{indM}) = str2func([...
'#(varargin)' ml{indM} '(slObj.innerTable,varargin{:})']);
end
slObj.methodHandles = tmpStruct;
end
function varargout = subsref(slObj,varargin)
S = struct(slObj);
varargout{:} = S.methodHandles.(varargin{1}.subs)(varargin{:});
end
end
end
(There's no need to fix the above code, I was just sharing)
I do not think the machine is the problem, but the class designer and he certainly has good motivations to seal the class. "Philosophy" of coding, a part, you could 'own' the class in a wrapper class without defining it sealed.
For example, supposer the class Hello is sealed and has a method (or function, if you wish) sayHello which you would like to use in inherited classes you could define a class FreeHello (public) which contains an instance of Hello. At the constructor you build the corresponding Hello and then you define a sayHello method whose body simply calls your Hello instance and makes it execute the sayHello method (and returns the output, accordingly).
In order to 'open' the sealed class, you need to do these for all properties and public methods; of course you are still not capable of accessing private methods, but now you can subclass your wrapper class, as you wish.
I'm trying to grab a method handle from within an object in MATLAB, yet something in the sort of str2func('obj.MethodName') is not working
The answer is to get a function handle as #Pablo has shown.
Note that your class should be derived from the handle class for this to work correctly (so that the object is passed by reference).
Consider the following example:
Hello.m
classdef hello < handle
properties
name = '';
end
methods
function this = hello()
this.name = 'world';
end
function say(this)
fprintf('Hello %s!\n', this.name);
end
end
end
Now we get a handle to the member function, and use it:
obj = hello(); %# create object
f = #obj.say; %# get handle to function
obj.name = 'there'; %# change object state
obj.say()
f()
The output:
Hello there!
Hello there!
However if we define it as a Value Class instead (change first line to classdef hello), the output would be different:
Hello there!
Hello world!
One could also write
fstr = 'say';
obj.(fstr)();
This has the advantage that it does not require a handle class to work if the object (obj) is modified.
Use #. The following code works for me:
f = #obj.MethodName
No other answer mimics str2func('obj.MethodName'). Actually, this one doesn't either, not exactly. But you can define an auxillary function like so:
function handle = method_handle(obj, mstr)
handle = #(varargin) obj.(mstr)(varargin{:});
end
Then method_handle(obj, 'MethodName') returns a handle to obj.MethodName. Unfortunately, you cannot pass the variable name of obj as a string - eval("obj") will be undefined in the function's scope.
I want to change the value of a property in a Matlab class from a function within the same matlab class. I.e on of the functions in the class is generating a value that I want to assign to a property for that class.
This is the properties of the class:
classdef myclass < handle
properties (SetAccess = public)
notional;
T;
u;
nbrAnnualPayments;
sigma_u;
sigma_s;
s_i;
N2;
cash_flow;
paymentDates;
detTP;
volTP;
..... and this is the set method.
function set.detTP(obj,value)
if ~(value > 0)
error('Property value must be positive')
else
obj.detTP = value;
end
end
Now I want to write something like:
obj.set.detTP(obj, value);
From another function to update the value of the detTP property.
How should i do this? How should the set function be written (i.e. is it written correctly now)? and how should the syntax look like for assigning the new value to the property.
Thanks in advance for your help!
You can simply write
obj.detTP = value;
or, if you'd use hgsetget instead of handle as the base-class, you could do
set(obj, 'detTP', value);
Your set-method looks fine at first sight.
I am trying to create an array of objects of a class Cell in another class Systemin MATLAB. The classCell` is:
classdef Cell
properties
ID;
EntityID;
ZoneID;
NeighborID;
State;
nextChangeTime;
end
methods
% Define the constructor
function obj = Cell()
obj.ID = zeros(1);
obj.EntityID = zeros(1);
obj.ZoneID = zeros(1);
obj.NeighborID = zeros(1);
obj.State = zeros(1);
obj.nextChangeTime = zeros(1);
end
end
Now I have another class System. I try to make an array of Cell objects like this:
classdef System
properties
Cells;
end
methods
function obj = System(dimx,dimy)
obj.Cells(dimx,dimy) = Cell();
end
end
But I think I am using the wrong format. Not sure if this is possible. Any suggestions on how to accomplish this would be appreciated.
In order to be able to create arrays of objects of user-defined class (e.g. Cell class), it is convenient to have the default constructor for the user-defined class. The default constructor is the one that takes no arguments (i.e. when nargin==0). When creating arrays, the implicit initialization of the array's objects is done by this constructor. If this constructor is missing, trying to build arrays by "extending" a scalar object will generate an error.
Another way of creating arrays of objects (without defining a default constructor) is by using horzcat, vertcat and cat.
Aaaaand... when accessing the properties of an object, don't forget to mention the object you're accessing:
obj.Cells = Cell.empty(0,0); % Force the type of empty Cells to Cell class
obj.Cells(dimx,dimy) = Cell();