What is purpose of abstract property in MATLAB? - 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

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.

Invoking method of a class as another class' attribute in 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?

How to separate Interface and common implementation

I have the following class hierarchy:
IMyObject % common interface defining methods and properties (abstract properties are supported by MATLAB)
A < IMyObject
B < IMyObject
...
IMyObject should act as interface and if possible not contain code.
There are many classes (A,B,...) derived from IMyObject and 90% of those share code for certain methods.
The straight forward way is to use an abstract class rather than an interface and just define all this code in IMyObject (possible renaming it to MyObjectRoot, MyObjectMaster, AbstractMyObject or similar). The 10% which do not share code of the mentioned methods would overwrite them.
However, I would like to have an explicit interface class (to separate the interface from code).
I use a "programming language" that supports multiple inheritance (MATLAB).
Now I may use the approach to create a class MyObject_GenericCode and the 90% classes would not only inherit from IMyObject but also from the MyObject_Generic class.
Since this generic class need access to the data (the abstract properties from IMyObject), they would also need to be derived from it.
Example:
MyObject_GenericCode < IMyObject
...
% the 90% classes having some kind of common code:
A < IMyObject & MyObject_GenericCode
B < IMyObject & MyObject_GenericCode
....
% 10% just use the interface and implement everything ob their own
Z < IMyObject
The problem is the diamond problem - but it's more theoretic in this case because I think there would not be such cases.
Apart from that - is there anything discouraging about that?
Finally, I found out that in MATLAB I can avoid this because the generic code classes do not need to be inherited from IMyObject but can still access the properties from the supplied object.
Example:
classdef IMyObject
properties (Abstract)
Fc;
end
methods (Abstract)
test(this);
end
end
classdef MyObject_GenericCode
methods
function test(this)
fprintf(1, 'Value of Fc: %d\n', this.Fc);
end
end
end
classdef A < IMyObject & MyObject_GenericCode
properties
Fc;
end
methods
function this = A()
this.Fc = 999;
end
end
end
myObj = A();
myObj.test();
which returns
Value of Fc: 999
without error. Although this works it sounds a bit "fishy" to me.
Which way is the appropriate option?
There is no need to use multiple inheritance in your case. Matlab's OOP does not have explicit interface classes, but if a class only consists of abstract methods and properties, in effect it acts like an interface. Generic class may implement a part of that interface, leaving some methods/properties abstract, to be implemented by a subclass.
So your hierarchy could look like this:
classdef IMyObject
properties (Abstract)
Fc;
end
methods (Abstract)
test(this);
end
end
classdef MyObject_GenericCode < IMyObject
properties (Abstract)
Fc;
end
methods
function test(this)
fprintf(1, 'Value of Fc: %d\n', this.Fc);
end
end
end
classdef A < MyObject_GenericCode
properties
Fc;
end
methods
function this = A()
this.Fc = 999;
end
end
end

implementing abstract methods in matlab

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.

What is the difference between calling a dependent property of a class with and without parentheses?

Say I have a class like such:
classdef exampleClass
properties (Dependent=true)
x
end
methods
function this=exampleClass(this)
this.x = 4;
end
function x=get.x(this)
x=4;
end
end
end
What's the difference in accessing x as classInstance.x and classInstance.x()?
The function get.x(this) is called a getter of the property x. It actually has nothing to do whether the property has the attribute Dependent or not, it is the same for any type of property.
If you have a setter/getter defined for your property, Matlab will always call the function get.PropertyName or set.PropertyName when you do something like:
tmp_var = my_instance.x
or
my_instance.x = 3.1416;
So if you have in your code my_instance.x or my_instance.x() is practically the same. But if you want to follow best practices, you must avoid the function call.
Now, as an extra point: for performance reasons, it is recommended that you do not use setters/getters because every time you modify your property (even inside your class) you will pay the price of the overhead of the setter/getter.