I am a Microsoft developer but trying to assist someone with some MATLAB code and design. I'm struggling to understand the syntax and usage of a class definition.
Code so far:
classdef Person
properties
Name
end
methods
function obj = Person(aName)
obj.Name = aName;
end
function ret = IsGraeme(obj)
if STRCMP( obj.Name , 'Graeme')
ret= 1;
else
ret= 0;
end
end
end
end
Now, I expect my usage to be similar to below:
graeme = Person('Graeme');
graeme.IsGraeme();
with the last line returning 1.
The first line of usage results in an error:
Too many inputs
The samples I have found on MATLAB seem to give you the classdef but not the usage.
I hope someone can help correct this simple example so that I can continue to build on it. (As mentioned, I am an experienced dev, just not in this language!).
UPDATE 1:
Using MATLAB 2013b.
Exact usage and resultant error below:
>> gt = Person('Graeme')
Error using Person
Too many input arguments.
The OP's solution ended up being running the clear command in MATLAB. In all likelihood, what happened is an old class definition was already stored in memory and for some reason was not automatically updated. Anyhow - an easy fix!
Just in case others who stumble on this question what an explanation of the simplest basics of class constructors...
In MATLAB, you can an instance of a class without a constructor function, you follow the approach shown here, summed up below:
>> gt = Person();
>> gt.Name = 'Graeme';
>> gt.IsGraeme();
The OP wanted to create a constructor so that he could assign values to the class object's properties at initialization. Just for clarity's sake, a constructor is:
a method having the same name as the class.
The below (modified to fit OP's use-case) code is essentially copied from here. The only difference here is that we first check whether an input value has been provided before attempting to assign a (potentially undefined) value to a property of the instantiated class object:
function gt = Person(aName)
if nargin > 0 % Check if more than 0 arguments are provided
gt.Name = aName; % Assign input argument to property
end
end
Now (as before), gt = Person('Graeme') will work as expected. This obviously assumes that the class is saved in a properly named M-file and that you've run clear to get rid of previous variable assignment mistakes.
Related
Hello lovely community,
i am quite new here, but still hope someone can help me out. I just worked a bit with Matlab in the past and want to do a new project. Earlier I just stored all in one Matlab file and didn't had the need to use classes. This has changed now, so I hope someone can explain me what I did wrong.
My desire is to create the project object based. Therefore I started creating new folders in the main folder:
C:\Users\Luftfahrt\MAV\
The folder names are:
+Data
+Model
After I read the first chapters of
A guide to MATLAB orientaded programming
I figured out that with the plus symbol I am creating public objects. Exactly as I want. In each folder I inserted an abstract Interface and a child for it.
DataLoaderIF
classdef DataLoaderIF< handle
methods (Abstract=true)
Data = LoadData(Asset,Start,End)
Status = getStatus(Obj)
Info = getInfo(Obj)
end
end
When i run this code above he is telling me that Abstract classes cannot be instantiated, but I did it exactly as in the book. Maybe I thought, it is stupid run code from an abstract interface, so that there is no problem, is that true?
DataLoader
classdef DataLoader < DataManager.DataLoaderIF
%Inheritent from DataLoaderIF. Is setting parameter and Importing
properties (Access=protected)
mStatus =-1; %nothing done
mInfo ='Import'; %
mData; %saving the imported data
mCollector; %to save the prices after structuring
end
methods
%creating the constructor
function Obj = DataManager
function getStatus(Obj)
mStatus=1;
end
function getInfo(Obj)
Info='Import';
mInfo= Info;
end
function LoadData(Asset,Start,End)
connection = yahoo;
mData= fetch(connection, Asset, Start,End, 'd');
close(connection)
%'JPY=X', '01-Jun-2011', datestr(now,'dd-mmm-yyyy'), 'd');
mCollector= [{'date' 'open' 'high' 'low' 'close' 'volume' 'adj-close'}
cellstr(datestr(mData(:,1))) num2cell(mData(:,2:end))];
end
end
What I wanted to do now is to create an Object and then give this Object the variables to perform the fetch. But how can I instantiate now the Object? He says my constructor is false.
Someone has some ideas?
P.S. I already looked here Documentation Matlab, but this didn't help me out.
Thanks a lot!
It is not clear what you want to do exactly and why you need an abstract class then a derived one, but assuming you really need all that for more purpose than you described, take the following into account:
By definition in OOP, an abstract class cannot be instantiated. It is only a basic framework for the different classes which will inherit from it, and you can only instantiate these inheriting classes. abstract classes are only useful if the different inheriting classes represent different objects but need to share a set of (almost) common methods. If not, forget the 'abstract' parent and just design the class that does what you need.
Be careful with the classes which inherit from the handle class. In Matlab they behave differently than the value classes. Read this article and decide which type you want.
If you decide to use a handle class, consider the following very important factor Initialising property value:
Initializing Properties to Unique Values
MATLAB assigns properties to the specified default values only once
when MATLAB loads the class definition. Therefore, if you initialize a
property value with a handle-class constructor, MATLAB calls this
constructor only once and every instance references the same handle
object. If you want a property value to be initialized to a new
instance of a handle object each time you create an object, assign the
property value in the constructor.
Now with all that in mind, below is a version of your class that does run, and that you can instantiate as below:
>> dl = DataLoader
dl =
DataLoader with no properties.
>> dl.getInfo
ans =
Import
>> dl.getStatus
ans =
-1
>> dl.LoadData(1,2,3) %// etc ...
The class definition is as follow
classdef DataLoader < DataLoaderIF
properties (Access=protected)
mStatus %// nothing done
mInfo %//
mData %// saving the imported data
mCollector %// to save the prices after structuring
end
methods
%// Constructor (and initialise default value). For classes which
%// inherit from the "handle" class it is very important to
%// intialise your default values IN THE CONSTRUCTOR, and NOT in
%// the property definition.
function obj = DataLoader
obj.mStatus = -1 ;
obj.mInfo = 'Import' ;
obj.mData = [] ;
obj.mCollector = [] ;
end
function Status = getStatus(obj)
Status = obj.mStatus ;
end
function Info = getInfo(obj)
%// a "get" type of function should not assign value, only
%// return information about the object.
Info = obj.mInfo ;
end
%// the "obj" parameter has to be the first parameter of the
%// function in it's signature.
function LoadData(obj,Asset,Start,End)
%// Put function help here
%// I don't know what this part of the code is supposed to do
%// so I leave it as it is. Be aware that the fucntion "fetch"
%// will have to be accessible in your context or the function
%// will error
connection = 'yahoo' ;
obj.mData = fetch(connection, Asset, Start , End, 'd') ;
close(connection)
obj.mCollector= [{'date' 'open' 'high' 'low' 'close' 'volume' 'adj-close'}
cellstr(datestr(obj.mData(:,1))) num2cell(obj.mData(:,2:end))];
%// Here do your own test with your own conditions to decide
%// what the status of the object should be.
if ~isempty(obj.mData) && ~isempty(obj.mCollector)
obj.Status = 1 ;
end
end
end
end
You seemed a bit confused on some concept of OOP. If your first contact with OOP is through Matlab I totally understand where you come from. I had the same experience and my understanding of OOP was wrong for many years (my OOP code was very poor and inefficient too as a result), until I properly learned my way in C++ and .Net. These last two languages are real OOP languages (I know, not the only ones, or even better one, I don't want to start a debate), in the sense that you need to understand the OOP concepts to get anything out of them. On the other hand, you can spend your life doing wonderful things on Matlab and remain blissfully unaware of what even OOP means.
OOP capability was introduced in Matlab as a "convenience" for programmers who missed this way of structuring their code. The first implementations were very clunky and unpractical (raise your hand if you remember having to code each and every one of your subassign, subsref, display, get, set etc for each single object !!). It has been drastically improved since then, until it is now something worth the extra coding effort if you want to get the benefit of OOP organisation (code reuse, polymorphism, inheritance etc ...). However, to this day the OOP syntax in Matlab remain un-instinctive at first even for OOP veterans (why the hell do we have to declare the object itself as the first parameter of the function, is the compiler so blind it does't see the function is in the class definition?). You just have to get used to it first, then it gets ok.
The Matlab documentation on OOP is mostly oriented to these veterans. It explains to people who knows OOP on another languages how to apply the concepts in the Matlab specific syntax. It is not at all a very good guide for pure beginners.
This (longer than I wanted, sorry) blurb, was to try to explain that:
If you need to learn OOP concepts, train yourself with another language first. (seriously, even with the learning curve of learning another language, you'll loose less time than with the trial and error approach on Matlab).
If you do not have a definite identified need for OOP code in Matlab, do not insist. You can do a lot of things (in fact almost everything) in Matlab without resorting to classes (at least not knowingly, of course you will use the base Matlab classes in the background, but you can use and maintain your car for many years without necessarily having an intimate knowledge of its every component).
Just having a little difficulty with the syntax of matlab functions;
function f = fact(x)
if x == 1
return
else
f = 1 - x*(fact(x-1))
end
end
When calling this function in the command window with the argument 10 I receive the error
Undefined function 'fact' for input arguments of type 'double'.
Error in recursion (line 6)
f = 1 - x*(fact(x-1))
I've had a look around and solutions for the first revolve around the pathing of the m-file which doesn't seem to be a problem as other files in the same directory run fine,
The second I'm not sure why the error in line 6 occurs, my guess is it has something to do with the variable and function names.
As a side question, are both these end statements necessary?
Thanks!
The most obvious error is your function filename. You have a function called fact defined in your code but you named your file recursion. Make sure that both your function name and the filename are both called fact.
If you were to name your file as recursion, then make the function name defined in your code as fact, this is what would happen if you tried calling your code:
>> f = recursion(10);
Undefined function 'fact' for input arguments of type 'double'.
Error in recursion (line 6)
f = 1 - x*(fact(x-1));
... look familiar?
As such make sure your filename and your function name are named the same. In fact, in the MATLAB editor, it should automatically give you an error saying that both of these are not the same.
There is also another error in your code. The base case is not defined properly. Always remember when you are writing recursive algorithms is that eventually the function is going to return... and that's when you hit the base case. We can see here that it is when x = 1. When x = 1, you're supposed to assign something to f which is the output. You are simply exiting the function, and so when x becomes 1, your code will spit out an error saying that f was not assigned when the function finishes. As such, you need to figure out what your base case is. I'm going to assume that your base case (when x = 1) is going to equal 0. You will obviously need to change this as I don't know what your code is actually computing. Basically, you need to do this:
function f = fact(x)
if x == 1
f = 0; %// Base case needs to change according to your specs
else
f = 1 - x*(fact(x-1))
end
end
When I do this, I get the following output when x = 10
>> f = fact(10);
f =
1334961
I don't get an error when I run this code now. Also, check to see if you have any variables named fact in your workspace. When this happens, you are in fact shadowing over your function with a variable, so it is actually trying to access the variable called fact instead. As such, try clearing your workspace by doing clear all;, then try this code again.
One warning
If you were to specify x to be 0 or negative, this function will never stop. As such, you need to provide some check and perform the proper action when this happens. Also, you need to make sure that you specify what type of inputs are accepted for x. Judging from the context, x are positive integers only. As what #Glen_b has noted, should you provide any number that isn't a positive integer, this function will never stop as x will never equal 1 down the recursion pipeline.
To answer your optional question
The first end statement is required to end the if statement. The second end statement isn't required, but it's good practice anyway. However, if you have multiple functions defined inside your function file, then yes it is most definitely required to properly signify that the end of that function is defined there. However, you don't need it if you're only writing one function per file, but I would recommend keeping it there as it's good practice.
I using pre-existing code in matlab that is organized into classes. Instead of using classdef it uses #folder's. I'm not entirely sure exactly how it works and its causing me some trouble.
The constructor format is as follows:
function this = crazy_class(varargin)
this.a = [];
this.b = [];
this = class(this, 'crazy_class');
end
I need to add a new property to the class, but if i modify it as so:
function this = crazy_class(varargin)
this.a = [];
this.b = [];
this.newProperty = [];
this = class(this, 'crazy_class');
end
I get the following:
Number of fields for class crazy_class cannot be changed without clear classes.
It doesn't like me adding a new unspecified property to the class. Fair enough, if there was a classdef, adding a new property would be simple, however I have no idea how to do this with the #folder format.
There is no .m file, or any file for that matter in the folder that specifies any properties for the class. The closest thing I can find are the overloaded functions:
subsasgn.m:
this = builtin('subsasgn', this, selector, value);
subsref.m:
r = builtin('subsref', this, selector);
But that's it. How does this class know what are valid properties and what aren't when they aren't mentioned in any other file. What am I supposed to look for to change this?
Edit: well this is embarrassing... I restarted Matlab and now everything works fine. I thought that by typing the command clear classes, or clear all would have done the trick but I guess it needed a full reboot.
The point is, you must now execute the command "clear classes", since there are existing class members with the old format. MATLAB told you that fact itself. The properties are defined in the crazy_class.m file.
You're working with 'old style' object-oriented code here. MATLAB 7.6 introduced the 'new-style' object-oriented syntax (using classdef etc), but prior to that you could use the style you're working with here, which is still supported but obsolete.
I'd suggest you take a look at the obsolete documentation, which is still available here. It will explain the details of the syntax, and how to work with these sort of classes.
As noted here, functions in packages, as well as static methods in classes, still need to use a packagename.functionname syntax or import packagename.* for each function (since the imports are part of the function workspace and not global). This means that changing the package/class name later on can become a tedious nuisance.
Is there any way to do something like import this.*, i.e. a package/class name agnostic method to access all functions/static methods in the same package/class?
So... doesn't this require importthis to also be imported? Or is importthis a function you always have in your path?
It seems hardly more complex to just paste an "import this" block with this at the top of each function, and then you don't have to worry about importthis being in your path. I tend to feel that reliance on path is dangerous.
"Import This" block
%% Import own package
[~, pkgdir] = fileparts(fileparts(mfilename('fullpath')));
import([pkgdir(2:end) '.*']);
You can even put it in a try/catch block to make sure it's in a package directory, and decide what to do if it's not.
%% Import own package
try
[~, pkgdir] = fileparts(fileparts(mfilename('fullpath')));
import([pkgdir(2:end)'.*']);
catch err
if ~strcmp(err.identifier,'MATLAB:UndefinedFunction'), rethrow(err); end
end
I recently ran into a similar problem and found the following solution for packages. However it is VERY hacky.
You create a function called import this with an optional argument.
function to_eval = importthis(exclude_list)
if nargin == 0
exclude_list = [];
end
var_name = genvarname('A', exclude_list); %avoid shadowing
to_eval = ['[~,'...
, var_name...
, ']=fileparts(fileparts(mfilename(''fullpath'')));'... %get containing dir
, 'eval([''import '','...
, var_name...
, '(2:end),''.*'']);'... %remove '+'
, 'clear '... %clean up
, var_name
];
end
This function returns a string which can then be evaled that imports the "this" package. So in your package functions you would put the following near the top:
function B = myfunc(A)
eval(importthis);
%function body
end
You can also pass who to importhis, leaving your function's namespace clean.
function B = myfunc(A)
eval(importthis(who));
%function body
end
I can't decide whether I should feel proud or discusted by what I did.
This probably is not a bounty worthy answer but as you do not have any answers I thought I would post it anyway! You can invoke static methods via an instance of the class which you would only need to define once. You can invoke functions via a function handle but this would require one handle per function.
Using these techniques you could define all your static method and function references in one place. Then you would use these references throughout your package. Then if you decided to change the package name at a later point you would only need to update these references which are all stored in one place.
See:
Calling Static Methods
You can also invoke static methods using an instance of the class,
like any method:
obj = MyClass;
value = obj.pi(.001);
function_handle (#)
The following example creates a function handle for the humps function
and assigns it to the variable fhandle.
fhandle = #humps;
I've come into ownership of a bunch of MATLAB code and have noticed a bunch of "magic numbers" scattered about the code. Typically, I like to make those constants in languages like C, Ruby, PHP, etc. When Googling this problem, I found that the "official" way of having constants is to define functions that return the constant value. Seems kludgey, especially because MATLAB can be finicky when allowing more than one function per file.
Is this really the best option?
I'm tempted to use / make something like the C Preprocessor to do this for me. (I found that something called mpp was made by someone else in a similar predicament, but it looks abandoned. The code doesn't compile, and I'm not sure if it would meet my needs.)
Matlab has constants now. The newer (R2008a+) "classdef" style of Matlab OOP lets you define constant class properties. This is probably the best option if you don't require back-compatibility to old Matlabs. (Or, conversely, is a good reason to abandon back-compatibility.)
Define them in a class.
classdef MyConstants
properties (Constant = true)
SECONDS_PER_HOUR = 60*60;
DISTANCE_TO_MOON_KM = 384403;
end
end
Then reference them from any other code using dot-qualification.
>> disp(MyConstants.SECONDS_PER_HOUR)
3600
See the Matlab documentation for "Object-Oriented Programming" under "User Guide" for all the details.
There are a couple minor gotchas. If code accidentally tries to write to a constant, instead of getting an error, it will create a local struct that masks the constants class.
>> MyConstants.SECONDS_PER_HOUR
ans =
3600
>> MyConstants.SECONDS_PER_HOUR = 42
MyConstants =
SECONDS_PER_HOUR: 42
>> whos
Name Size Bytes Class Attributes
MyConstants 1x1 132 struct
ans 1x1 8 double
But the damage is local. And if you want to be thorough, you can protect against it by calling the MyConstants() constructor at the beginning of a function, which forces Matlab to parse it as a class name in that scope. (IMHO this is overkill, but it's there if you want it.)
function broken_constant_use
MyConstants(); % "import" to protect assignment
MyConstants.SECONDS_PER_HOUR = 42 % this bug is a syntax error now
The other gotcha is that classdef properties and methods, especially statics like this, are slow. On my machine, reading this constant is about 100x slower than calling a plain function (22 usec vs. 0.2 usec, see this question). If you're using a constant inside a loop, copy it to a local variable before entering the loop. If for some reason you must use direct access of constants, go with a plain function that returns the value.
For the sake of your sanity, stay away from the preprocessor stuff. Getting that to work inside the Matlab IDE and debugger (which are very useful) would require deep and terrible hacks.
I usually just define a variable with UPPER_CASE and place near the top of the file. But you have to take the responsibly of not changing its value.
Otherwise you can use MATLAB classes to define named constants.
MATLAB doesn't have an exact const equivalent. I recommend NOT using global for constants - for one thing, you need to make sure they are declared everywhere you want to use them. I would create a function that returns the value(s) you want. You might check out this blog post for some ideas.
You might some of these answers How do I create enumerated types in MATLAB? useful. But in short, no there is not a "one-line" way of specifying variables whose value shouldn't change after initial setting in MATLAB.
Any way you do it, it will still be somewhat of a kludge. In past projects, my approach to this was to define all the constants as global variables in one script file, invoke the script at the beginning of program execution to initialize the variables, and include "global MYCONST;" statements at the beginning of any function that needed to use MYCONST. Whether or not this approach is superior to the "official" way of defining a function to return a constant value is a matter of opinion that one could argue either way. Neither way is ideal.
My way of dealing with constants that I want to pass to other functions is to use a struct:
% Define constants
params.PI = 3.1416;
params.SQRT2 = 1.414;
% Call a function which needs one or more of the constants
myFunction( params );
It's not as clean as C header files, but it does the job and avoids MATLAB globals. If you wanted the constants all defined in a separate file (e.g., getConstants.m), that would also be easy:
params = getConstants();
Don't call a constant using myClass.myconst without creating an instance first! Unless speed is not an issue. I was under the impression that the first call to a constant property would create an instance and then all future calls would reference that instance, (Properties with Constant Values), but I no longer believe that to be the case. I created a very basic test function of the form:
tic;
for n = 1:N
a = myObj.field;
end
t = toc;
With classes defined like:
classdef TestObj
properties
field = 10;
end
end
or:
classdef TestHandleObj < handle
properties
field = 10;
end
end
or:
classdef TestConstant
properties (Constant)
field = 10;
end
end
For different cases of objects, handle-objects, nested objects etc (as well as assignment operations). Note that these were all scalars; I didn't investigate arrays, cells or chars. For N = 1,000,000 my results (for total elapsed time) were:
Access(s) Assign(s) Type of object/call
0.0034 0.0042 'myObj.field'
0.0033 0.0042 'myStruct.field'
0.0034 0.0033 'myVar' //Plain old workspace evaluation
0.0033 0.0042 'myNestedObj.obj.field'
0.1581 0.3066 'myHandleObj.field'
0.1694 0.3124 'myNestedHandleObj.handleObj.field'
29.2161 - 'TestConstant.const' //Call directly to class(supposed to be faster)
0.0034 - 'myTestConstant.const' //Create an instance of TestConstant
0.0051 0.0078 'TestObj > methods' //This calls get and set methods that loop internally
0.1574 0.3053 'TestHandleObj > methods' //get and set methods (internal loop)
I also created a Java class and ran a similar test:
12.18 17.53 'jObj.field > in matlab for loop'
0.0043 0.0039 'jObj.get and jObj.set loop N times internally'
The overhead in calling the Java object is high, but within the object, simple access and assign operations happen as fast as regular matlab objects. If you want reference behavior to boot, Java may be the way to go. I did not investigate object calls within nested functions, but I've seen some weird things. Also, the profiler is garbage when it comes to a lot of this stuff, which is why I switched to manually saving the times.
For reference, the Java class used:
public class JtestObj {
public double field = 10;
public double getMe() {
double N = 1000000;
double val = 0;
for (int i = 1; i < N; i++) {
val = this.field;
}
return val;
}
public void setMe(double val) {
double N = 1000000;
for (int i = 1; i < N; i++){
this.field = val;
}
}
}
On a related note, here's a link to a table of NIST constants: ascii table and a matlab function that returns a struct with those listed values: Matlab FileExchange
I use a script with simple constants in capitals and include teh script in other scripts tr=that beed them.
LEFT = 1;
DOWN = 2;
RIGHT = 3; etc.
I do not mind about these being not constant. If I write "LEFT=3" then I wupold be plain stupid and there is no cure against stupidity anyway, so I do not bother.
But I really hate the fact that this method clutters up my workspace with variables that I would never have to inspect. And I also do not like to use sothing like "turn(MyConstants.LEFT)" because this makes longer statements like a zillion chars wide, making my code unreadible.
What I would need is not a variable but a possibility to have real pre-compiler constants. That is: strings that are replaced by values just before executing the code. That is how it should be. A constant should not have to be a variable. It is only meant to make your code more readible and maintainable. MathWorks: PLEASE, PLEASE, PLEASE. It can't be that hard to implement this. . .