I'm new to MATLAB OOP. I have an abstract class defining an abstract method in my matlab path. I have a subclass named SubAbsClass in a subfolder named #SubAbsClass. I cannot create an object of the subclass after implementing the abstract method in the subclass. Here's my SubAbsClass implementation:
classdef SubAbsClass < AbsClass
properties
O1
end
methods
function obj=SubAbsClass(a,b)
obj.O1=absMethod(a,b);
end
end
methods (Static)
function out = absMethod(a,b)
out = a + b;
end
end
end
and my abstract class implementation is:
classdef AbsClass
methods(Abstract, Static)
result = absMethod
end
end
when I try to create an object in the MATLAB path (the abstract class is in the MATLAB path), I get an error. I have tried many configurations and searched the matlab oop document, and also the web including stackoverflow but unfortunately couldn't find an example to implement. I appreciate your help
>> clear all; clear classes;
>> obj=SubAbsClass(5,2)
Undefined function 'absMethod' for input arguments of type 'double'.
Error in SubAbsClass (line 11)
obj.O1=absMethod(a,b);
Within a method, Matlab considers non-dot references to be calls to local functions (defined outside the classdef block within the class file) or to a function somewhere on the Matlab path following the usual look-up rules.
So you need to call the Static method via the instance obj in the constructor:
methods
function obj = SubAbsClass(a,b)
obj.O1 = obj.absMethod(a,b);
end
end
One little caveat to the above is that non-Static methods also have a functional form.
So if the method was not Static, this notation would also work
methods
function obj = SubAbsClass(a,b)
obj.O1 = absMethod(obj,a,b);
end
end
Which, I think, is almost equivalent to the dot notation, although it has been said to be "generally" faster (albeit, that was four years ago).
Here are the details for ordinary method invocation and Static method invocation.
Related
I have a class, for which I have static methods that calculate something (example below in MATLAB, since that's what I'm using, although I think my question may be more general):
methods (Static)
function out = f(x)
out = x*2;
end
end
Suppose I have instance methods where I want to do the same calculation (and hence use the aforementioned class method), but I also want to do something specific to the class, like updating a property or maybe passing in an instance property into the calculation. So like:
methods
function out = f(this)
out = ClassName.f(this.x); % Use the class method, but pass in an instance variable
end
% OR
function [this, out] = f(this,x)
out = ClassName.f(x)*2; % Use the class method with a provided input
this.value = out; % then assign value to an instance variable
end
end
At least in MATLAB, I can't overload a class method with an instance method (I can overload a built-in MATLAB method within my class, but that's not what I want here), so I'm not sure how to go about this in a proper OOP way. I want to keep the class method there in case someone wants to use the specific calculation on some data they collected outside the class, but I also want the instance method in case someone decides to use the class to collect data and then analyze the data with the built methods.
I tried to change an attribute value of a class by invoking one of its member function:
p1 = tank();
p1.checkOri(p1);
And in the class definition, I have that static method:
classdef tank
properties
value
...
end
methods
...
methods (Static)
function obj = checkOri(obj)
if (CONDITION) %the thing I want it to do
obj.value = EXPRESSION;
...
Yet this checkOri method is not working. But if I write this method in the main file, or to say altering the value of p1-the instance of class tank-it works perfectly:
p1 = tank();
p1.checkOri(p1);
if (CONDITION) %the thing I want it to do
p1.value = EXPRESSION;
It works perfectly.
I wonder what caused this. From my experience with other programming languages, invoking method should have worked, is it because of some tricks with Matlab syntax or static method? How could I fix it so that this method would work?
So, as #Navan in the comment said, handle class could be a solution.
It appears Matlab has a similar parameter concept with Java and C++, arguments modified in a function/method only remains that modification inside the function/method.
For this class, I simply added < handle in the head of class definition and it worked:
classdef tank < handle
properties
...
But I am not sure if that is the only solution, there might be better ways to do this. So I'll leave that question open, you are more than welcomed to post your opinion:D
In MATLAB, the call
p1.checkOri();
is equivalent to
checkOri(p1);
In both cases, the class method checkOri is called for the class of object p1, passing p1 as first argument to the function by value.
Because p1 is passed by value, any changes made to it inside the function are not seen by the object in the calling workspace. Therefore, one typically does
p1 = checkOri(p1);
This way, the object that was passed by value and modified inside the function is passed back out and assigned to the variable that held the original object.
If the method is written as follows:
function obj = checkOri(obj)
%...
end
then MATLAB will optimize the above function call such that no copy of the object is actually made. Note that both in the function declaration and in the function call, the input and output variable is the same.
As already discovered by OP, the above does not hold for handle classes, classes that inherit from handle. These classes act as if they are always passed by reference, and any change made to them in any workspace will be reflected in all other copies in other workspaces.
Also assigning to a member variable does not follow the above, such that
p1.value = 0;
modifies object p1.
For more information on the difference between value classes and handle classes see this other question.
I have this
classdef what
properties ( ... )
...
end
methods (Access=public)
...
end
methods
function obj = what(...) ... end % constructor
function test = Test1() ... end
function test = Test2() ... end
end
The constructor has a lot of constraints in it such that when I create the what it fails if the conditions are not met, the constraints are tested by calling Test1 and Test2.
I have stored the test functions also under methods, and I want these to be hidden so that they don't show up outside the classdef. but I get thrown an error for Test1 and Test2.
I want these Test functions to be private, hidden, and only related to this class but I also want it to be call-able when using the constructor function found in methods, My question is: what would be the 'correct' place and method to store these functions.
I am currently getting an error when I use the constructor function, however, if I add the functions in the bottom of the page outside the classdef then the functions work but I am not sure if this is good practice and why I can't have the test functions in the method section.
There are several ways to deal with this.
In general, private functions are placed inside a methods (Access = private) block. Sometimes they can also be made static, if this makes sense. Private methods can also be placed in a separate folder.
classdef what
methods % no properties here
function obj = what(varargin) % constructor
...
out = obj.Test1(in); % object method calling example
...
end
end
methods (Access = private)
function tf = Test1(varargin)
...
end
% etc ...
end
If these functions are only ever used by the constructor, you can make them nested:
classdef what
methods % no properties here
function obj = what(varargin) % constructor
...
out = Test1(in); % no need for "obj" here
...
function tf = Test1(varargin)
...
end % Test1
end % constructor
end % methods
As mentioned by Cris, you can also put functions after the classdef block:
classdef what
...
end
function tf = Test1(varargin)
end
The suggestions above should solve your problem. Now for some other comments:
It's probably not a goot idea to name your class what, as this is a name of a builtin MATLAB function.
While it is possible to set a private method block to be Hidden, this is generally not needed in order to "hide" private methods, as these are not visible outside the class anyway.
I would personally suggest sticking to a certain naming convention (e.g. Pascal or Java) (this is referring to the class name which is lowercase as opposed to the "Test" methods which are uppercase).
If you're fairly new to MATLAB OOP, you might want to read about Handle Classes.
Matlab allows for class methods to be both abstract and static, which is different than many OO languages. After trying a few cases, however, it's unclear to me how this can be used in actual code. Consider this sample abstract class:
classdef (Abstract) TestParent
methods (Access = public, Abstract = true, Static = true)
f()
end
methods (Access = public, Static = true)
function g()
disp('Test g');
TestParent.f(); % This line will cause problems
end
end
end
And consider this concrete child class:
classdef TestChild < TestParent
methods (Access = public, Static = true)
function f()
disp('f child');
end
end
end
As noted in the comment on the class TestParent, the call to the abstract static f() will fail at runtime. Specifically, from the command line, using the child class, I get:
>> TestChild.f()
f child
>> TestChild.g()
Test g
Error using TestParent.f
Method 'f' is not defined for class 'TestParent' or is removed from MATLAB's search path.
Error in TestParent.g (line 13)
TestParent.f();
On the command line using the parent class, I get:
>> TestParent.g()
Test g
Error using TestParent.f
Method 'f' is not defined for class 'TestParent' or is removed from MATLAB's search path.
Error in TestParent.g (line 13)
TestParent.f();
So, in summary:
I can call f on the child class with no problem. This makes sense since it has a concrete implementation in the child class. So far so good.
If I try to call g using the parent class name as a qualifier, the code crashes when it needs to call the abstract static method f. This makes sense since the parent has no implementation of f and the call path did not go through any concrete child.
If I try to call g from the child class, it recognizes that the child class has no local method with that name and goes to the parent class, where it finds and attempts to run the parent's implementation of g. In this case, I was expecting it to run successfully since the call path does logically imply a concrete implementation of f that should be run. Nonetheless it crashes.
The last one is the real surprise to me. I expected that if static and abstract meant anything, it would mean that this is supported. Given that this is apparently not supported, I'm unable to see why this combination of keywords makes sense. Can anyone give a use case for this?
I'm having some trouble creating classes in matlab and I don't really understand the method behind it (i'm fairly new to it)
here is my attempt at basic addition using matlab
classdef test
properties
a
b
end
methods
function add = plus(a, b)
end
end
end
assigning values via
p=test(), p.a=5
etc seems to work fine, however attempting p.add returns the error
No appropriate method, property, or field add for class test.
Any help or guidance would be appretiated, thanks.
Methods are defined exactly as functions are with respect to names and outputs.
Therefore, the method is called plus, the output the method should calculate is called add, and the way you probably wanted to write the method is:
function out = add(this)
out = this.a + this.b;
end
Now you call the method as
p.add();