Invoking method of a class as another class' attribute in Matlab - matlab

Apologize if the title is confusing.
I tried to set an attribute of a class as another class:
classdef gun
properties
bullets;
...
Where bullets is later initialized as another class object bullets = bul(10);
classdef bul
properties
...
methods
function obj = addBullet(obj, num)
...
But when I tried to invoke method addBullet in class gun, like gun.bullets.addBullet(2), I got an error saying:
Dot indexing is not supported for variables of this type.
Is it because Matlab does not support class as another class' attribute? Any way I can fix that?

Related

Why does MATLAB attempt to instantiate abstract properties?

There is unexpected (to me) behavior when combining class property validation with abstract properties in MATLAB. Here is a short example involving three classes:
classdef TestClass
properties (Abstract)
aprop (1,1) TestClassB
end
end
classdef TestClassB
methods
function obj = TestClassB(a)
disp(a);
end
end
end
classdef TestClassC < TestClass
properties
aprop
end
end
Then, when attempting to instantiate a TestClassC object, I get the following error:
>> TestClassC()
Error defining property 'aprop' of class 'TestClass'. Unable to construct default
object of class TestClassB.
Evidently, MATLAB is trying to instantiate the abstract property aprop in TestClass and then fails due to the lack of a valid zero-argument constructor in aprop's class definition TestClassB. I realize that the zero-argument constructor issue is in theory fixable (although only if you have access to modify TestClassB), but the fact that MATLAB is instantiating an abstract property at all seems very strange. The first line of the Wikipedia article on abstract types literally states:
...an abstract type is a type in a nominative type system that cannot be instantiated directly...
Perhaps this is the only way that MATLAB, as a weakly typed language, can implement property validation, but this is an unfortunate result.
On a side note, if TestClassB has a valid zero-argument constructor but is defined to be abstract, you end up falling into the same trap but with a slightly different error:
>> TestClassC()
Error defining property 'aprop' of class 'TestClass'. Class TestClassB is abstract.
Specify a default value for property aprop.
Is there a good reason for this behavior?
Edit:
Additional test-class observations
Removing the size validation in TestClass eliminates the error. Evidently, MATLAB has no problem initializing a empty array of objects without a valid zero-argument constructor. Note: this only works when TestClassB is not abstract.
If TestClassB is abstract and TestClassC initializes aprop in the property block with a concrete subclass of TestClassB, there is no error (assuming that the concrete subclass has a valid zero-argument constructor). Note: this is not true if aprop is instead initialized in TestClassC's constructor.
Motivating example
The above UML diagram is a typical example of combining inheritance with composition. GenericCar and GenericEngine are abstract classes. GenericCar contains a GenericEngine, but Racecar specifies its engine as a concrete V8 (which "isa" GenericEngine). Unfortunately, this can't be constructed using property validation in MATLAB since MATLAB will not allow you to re-define the class of an abstract property even if it is a subclass of the original definition.
Suppose you accept that you can't define engine in Racecar as a V8. Even so, if you don't supply an initial value for engine in the property block of Racecar, MATLAB will throw an error when creating a Racecar object since it will try to initialize engine using the abstract type GenericEngine. This is true even if the constructor of Racecar initializes engine as a V8 object. This highlights the odd connection between property validation and object instantiation.
It seems that two questions should be answered:
1 - "Evidently, MATLAB is trying to instantiate the abstract property aprop in TestClass. So why does MATLAB attempt to instantiate abstract properties?"
According to the documentation (emphasis is by me):
You can define property validation for abstract properties. The validation applies to all subclasses that implement the property.
MATLAB is trying to instantiate the property aprop in TestClassC that is a concrete subclass of TestClass. But it uses the same validation rules that is used in TestClass. The aprop property of TestClassC isn't abstract.
2 - "If TestClassB ... is defined to be abstract, you end up falling into the same trap..."
Referring to the documentation:
abstract class — A class that cannot be instantiated, but that defines class components used by subclasses.
TestClassC uses the same validation rules that is used in TestClass. It tries to instantiate its aprop member that is of class TestClassB but TestClassB is abstract and cannot be instantiated.

Matlab alter attribute value by method

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.

Import class to access constant values

I defined a class in one of my many MATLAB packages. To my suprise, I could not access a constant property of my class without importing the class definition. Even if it is a method of the class itself. Like so:
classdef TestClass
properties( Constant )
c=0;
end
methods
function obj = TestClass()
end
function getC(obj)
import test.TestClass;
disp(TestClass.c);
end
end
end
I just want to check whether I am doing something wrong here or is this the correct way to use constants in MATLAB.
Since you have placed TestClass inside a package Matlab needs to know where to look to find the definition for this class, even if it's a reference from within the class or function. An alternate to the above code could be:
function getC(obj)
disp(test.TestClass.c);
end
Alternately, if within a class, constant values can be accessed from the object itself.
function getC(obj)
disp(obj.c);
end
If neither of these is working for you, you may need to refresh the classdef for TestClass from memory. This will cause matlab to reload the constant value, which is pulled into Matlab when it first parses the classdef file to determine the structure of the class. This can be done using clear classes, however a warning that it will also clear all other classes, variables, and any breakpoints you have set.
If you want to see if this is necessary you can view the metaclass object to determine what Matlab "thinks" your class structure should be. You can do this using the following.
mc = ?test.TestClass;
mc.PropertyList
You may need to index into the property list to find the specific property you are interested in, but the thing you are looking for are the following fields.
Name: 'c'
Constant: 1
DefaultValue: 0

What is purpose of abstract property in MATLAB?

We have the abstract attribute of methods and properties in MATLAB R2014b, and I know the purpose of abstract attribute for methods. We can call functions in that method and define it in the superclass of a class. What I'm confused about is the purpose of the abstract attribute for a property in MATLAB. How do we use this?
The purpose of abstract properties (and abstract methods) is to allow the creation of interfaces:
The basic idea of an interface class is to specify the properties and methods that each subclass must implement without defining the actual implementation.
For example, you can define an abstract Car with the definition
classdef (Abstract) Car
properties(Abstract) % Initialization is not allowed
model
manufacturer
end
end
The abstract properties model and manufacturer cannot be initialized (that would be like instantiating an abstract class) and all classes that inherit from Car must specify their value for the subclass to be concrete.
If the properties were not abstract, the subclass would simply inherit them.
Making the properties abstract forms a contract of sorts that says "for you to be a usable (concrete) car you must have a model and manufacturer defined".
Therefore, in the definition
classdef FirstEveryManCar < Car
properties
model = 'T';
manufacturer = 'Ford';
end
end
the property definitions are compulsory for the class to not be made abstract automatically (which you could do if you have long class hierarchies).
There is a significant consequence for setter/getter methods (i.e. set.Property & get.Property).
Due to the way Matlab works, you can only implement setter/getter methods inside the class definition file of the class that declares the property. Therefore if you want to ensure a property is defined in the interface, but require implementation specific setter/getter methods, then declaring the property Abstract in the interface class ensures the subclass redefines the property and enables that class to define its own setter/getter methods.
Example 1 (Does not work)
Superclass
classdef (Abstract) TestClass1 < handle
properties
Prop
end
end
Subclass
classdef TestClass2 < TestClass1
methods
function obj = TestClass2(PropVal)
if nargin>0
obj.Prop = PropVal;
end
end
function set.Prop(obj, val)
if ~isnumeric(val)
error('Not a number!');
end
obj.Prop = val;
end
end
end
Example 2 (The correct way)
Superclass
classdef (Abstract) TestClass1 < handle
properties (Abstract)
Prop
end
end
Subclass
classdef TestClass2 < TestClass1
properties
Prop
end
methods
function obj = TestClass2(PropVal)
if nargin>0
obj.Prop = PropVal;
end
end
function set.Prop(obj, val)
if ~isnumeric(val)
error('Not a number!');
end
obj.Prop = val;
end
end
end
I don't know any example where you really need it, but it is typically used when a abstract superclass uses properties without having a reasonable default. This is a extremely trimmed down example, but imagine welcome implementing a full user interface while welcomeGer fills all required properties to provide it in german language:
%welcome.m
classdef welcome
properties(Abstract)
text
end
methods
function printText(obj)
disp(obj.text)
end
end
end
%welcomeGer.m
classdef welcomeGer<welcome
properties
text='Willkommen in unserem Hotel'
end
end
Alternative you could skip the definition of text at all, but then matlab would not throw an error when you forget to initialize text

Dynamically add a field to an object in matlab

Say I have a MATLAB object defined in a class file
classdef foo
properties
bar
end
end
And I create a foo object
myfoo = foo();
Now I want to add another field to foo dynamically. What I want is
myfoo.newfield = 42;
but this will throw an error.
I know there is a way to dynamically add a field/property to a MATLAB object but I can't remember it or find it easily in the help. Anyone know the syntax?
Ok, found it. But it's not general, only subclasses of the dynamicprops class implement it.
This is what I remember coming across. So I suspect the general answer to this question is you can't do it.
Any class that is a subclass of the dynamicprops class (which is itself a subclass of the handle class) can define dynamic properties using the addprop method. The syntax is:
P = addprop(H,'PropertyName')