MATLAB OOP: Communication between objects of different subclasses - oop

I am at the beginning of a bigger project, where I have to rewrite existing MATLAB script code. I was asked to use MATLAB's object oriented programming support to get a more flexible and robust program.
I got to a point, where I wondered how to let objects of different subclasses communicate or better: what is the best or most elegant/efficient/user friendly way to do that.
Example:
Superclass A (handle class):
classdef A < handle
properties
myvar
end
methods (Access = protected)
function calc_myvar(obj)
%calculate myvar with some code
obj.myvar=...;
end
end
end
Subclass B:
classdef B < A
properties
subclassvar
end
methods (Access = protected)
function calc_subclassvar(obj)
%calculate subclassvar with some code
%needs myvar of an object of class C
%C.myvar
obj.subclassvar=...;
end
end
end
Subclass C:
classdef C < A
properties
%some other properties
end
methods
%some other methods
end
end
So subclass B needs a variable of subclass C that is defined in A. At the moment I always pass an object of C as additional input parameter to the function. Additionally I don't know if C.myvar already has a value.
Current implementation:
function calc_subclassvar(obj,C)
if isempty(C.myvar)
C.calc_myvar;
end
obj.subclassvar = do_something_with_C.myvar;
end
Is there another, better way? I read of overloading the get function, so I don't have to check everytime if the variable exists? And I read about events and listeners but couldn't get it to work satisfactorily. For example if I want to add a listener to C it has to know from which specific object of A the event is sent. Or is there a way that C just listens for any object of A?
Maybe you know another way. It's kind of confusing. =)

I think you are over complicating the problem a bit. Either that, or I do not completely understand what you are asking for.
First of all, you are not using any constructors. I would normally use those to pass references to objects needed in a given class at instance-time. Secondly, you write that you don't know if C has been initialized when you need it in B. I see that as a lack of structure in your program, so if a part of your restructuring task is to make the program more robust, this would be a good place to start. Unless you have really good reasons against it, you should be able to tell in which order different objects are being initialized. Using constructors as explained above forces you to consider this, as you can't instance C without an instance of B in your example.
Below are my version of B and C. I excluded A as the need for inheritance is not really concerned with this problem.
Class C:
classdef C < handle
properties
some_const = pi;
end
methods
%some other methods
end
end
Class B:
classdef B < handle
properties
C_handle
end
methods (Access = public)
function obj = B(C_handle)
obj.C_handle = C_handle;
end
function disp_c_var(obj)
disp(obj.C_handle.some_const)
end
end
end
Use of the classes:
c_inst = C();
b_inst = B(c_inst);
b_inst.disp_c_var();
Now, all subsequent uses of b_inst already have a reference to c_inst, so it wont have to be passed again.

Related

How to limit the scope of a variable to the function when declared in an If statement

I need to limit the scope of a variable to the function it resides with however I need to declare it within an if statement as it's type will change depending. I'm working within VB.NET
Public Function CourseDataTable()
If RadioCourses.Checked Then
Dim SearchBy As New classSearchCourses
ElseIf RadioAttendees.Checked Then
Dim SearchBy As New classSearchAttendees
End If
The obvious problem is that the variable doesn't persist outside of the if statement. I want to limit the scope of this variable because a, it's used else where and b, memory leakage, the class could very well end up holding whole SQL tables and I don't want that persisting when it's not needed.
I can't use inheritance or polymorph here because I'm working a legacy system.
This is probably a rework (I'm struggling think of a different way of approaching it evidently) as I can't find anything in MSDN that allows procedure scope but ignores any other blocks at declaration.
It is still possible to use polymorphism in a legacy system. What you can do is find the common functionality that must exist between the two in order for you to even want to reuse the same variable. Then you can create wrapper classes for each of these legacy classes. The wrapper class would implement the common interface and simply call the underlying legacy implementation. Then you simply declare a variable to that common Interface and create the appropriate wrapper class instance inside of the if statements.
Edit: If you have the ability to modify the legacy classes at all, a simpler solution would be to simply create a common Interface that both of the legacy classes can implement. This will give you the polymorphic functionality that you desire without the need of wrapper classes. VB.Net even provides the ability to implement an interface in a way to where the interface methods are only exposed by a Interface reference. To do this, you simply mark the interface implementation methods as Private.
You could just declare SearchBy as Object and then do something like this
Dim searchBy As Object
If RadioCourses.Checked Then
searchBy = New classSearchCourses
ElseIf RadioAttendees.Checked Then
searchBy = New classSearchAttendees
End If
If searchBy.GetType() Is GetType(classSearchCourses) Then
'Do something
ElseIf searchBy.GetType() Is GetType(classSearchAttendees) Then
'Do something else
End If
This is still inheritance though since most everything inherits from System.Object but it will save you declaring your own new base class if for some reason you can't do that

Matlab: Class destructor not called during clear?

In Matlab I have a class
classdef myClass
properties
% some properties here...
end
methods ( Access = 'public' )
function obj = myClass()
% constructor...
end
function obj = delete( obj )
% suppose to be destructor...
fprintf(1, 'delete\n');
end
end % public methods
end
What is the default behavior of Matlab when I clear a variable of type myClass?
For example:
>> m = myClass();
>> clear m
I would expect Matlab to call the destructor of m at this stage, but it seems like it doesn't!!
My questions:
How can I force a call to the destructor when clearing a variable?
Is this default behavior of Matlab's makes any sense? Isn't it more logical to call the destructor when clearing a variable?
Is it possible that Matlab's classes do not have a detructor method (that is, there is no default method to be called when the class is destroyed)? Or am I missing something?
Is it possible that only classes derived from handle have a destructor (the delete method)?
Thanks!
EDIT : following Jonas' answer, a brief summary:
Matlab has two types of classes: value classes (the default) and handle classes (derived from handle super class). Value classes tends to provide better performance, however, they do not have a destructor functionality.
handle classes do have a destructor function: delete that is called when the class is destroyed. See this question from more details on handle class destructors.
If one wishes to have a destructor-like functionality for value classes, Jona's answer proposes a method utilizing onCleanup functionality.
Thanks for the good answer and the insightful comments!
Delete is only defined as class destructor for handle classes, not value classes (so the answer to Q4 is "yes", see the previous link to the documentation). Value classes work very much like standard Matlab arrays, in that they're passed by value rather than by reference, and in that many of the internals, such as destructors, are hidden from the user. In exchange, they're usually faster (see for example this SO question).
Consequently, I suggest to use the onCleanup functionality if you want to have a delete method being called (note that delete(m) will not actually delete anything, so you may want to make that a private method).
classdef myTestClass
properties
% some properties here...
end
properties (Hidden)
cleanup
end
methods ( Access = 'public' )
function obj = myTestClass()
% constructor...
obj.cleanup = onCleanup(#()delete(obj));
end
end
methods ( Access = 'private' )
%# I suggest hiding the delete method, since it does not
%# actually delete anything
function obj = delete( obj )
fprintf(1, 'delete\n');
end
end % public methods
end

How to call appropriate subclass constructor inside base class constructor in MATLAB

I'm trying to use single inheritance in Matlab, and to write a base class constructor that allows the creation of arrays of objects, including empty arrays, and which is inherited by subclasses. I can't work out how to do it without using some incredibly clunky code. There must be a better way.
In this toy example, my base class is called MyBaseClass, and my subclass is called MySubClass. Each can be constructed with a single numeric argument, or no arguments (in which case NaN is assumed). In the toy example my SubClass is trivial and doesn't extend the behavior of MyBaseClass in any way, but obviously in practice it would do more stuff.
I want to be able to call the constructor of each as follows:
obj = MyBaseClass; % default constructor of 'NaN-like' object
obj = MyBaseClass([]); % create an empty 0x0 array of type MyBaseClass
obj = MyBaseClass(1); % create a 1x1 array of MyBaseClass with value 1
obj = MyBaseClass([1 2; 3 4]) % create a 2x2 array of MyBaseClass with values 1, 2, 3, 4.
And the same four calls for MySubClass.
The solution I have found needs to call eval(class(obj)) in order to recover the subclass name and construct code in strings to call while in the base class constructor. This seems clunky and bad. (And it's somewhat surprising to me that it's possible, but it is.) I guess I could duplicate more logic between the MyBaseClass and MySubClass constructors, but that also seems clunky and bad, and misses the point of inheritance. Is there a better way?
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% MyBaseClass.m
classdef MyBaseClass
properties
data = NaN
end
methods
% constructor
function obj = MyBaseClass(varargin)
if nargin == 0
% Handle the no-argument case
return
end
arg = varargin{1};
% assume arg is a numeric array
if isempty(arg)
% Handle the case ClassName([])
% Can't write this, because of subclasses:
% obj = MyBaseClass.empty(size(arg));
obj = eval([class(obj) '.empty(size(arg))']);
return
end
% arg is an array
% Make obj an array of the correct size by allocating the nth
% element. Need to recurse for the no-argument case of the
% relevant class constructor, which might not be this one.
% Can't write this, because of subclasses
% obj(numel(arg)) = MyBaseClass;
obj(numel(arg)) = eval(class(obj));
% Rest of the constructor - obviously in this toy example,
% could be simplified.
wh = ~isnan(arg);
for i = find(wh(:))'
obj(i).data = arg(i);
end
% And reshape to the size of the original
obj = reshape(obj, size(arg));
end
end
end
% end of MyBaseClass.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% MySubClass.m
classdef MySubClass < MyBaseClass
methods
function obj = MySubClass(varargin)
obj = obj#MyBaseClass(varargin{:});
end
end
end
% end of MySubClass.m
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Your solution is functional and embraces some loose MATLAB typing to achieve what you want. However, getting clean and structured OOP is probably going to require losing some of the functionality you want. At the same time, the best option for avoiding code duplication is templated/generic container classes but these are not supported in MATLAB at this time.
Your code mirrors the MATLAB documentation on Building Arrays in the Constructor and relies on MATLAB being a loosely typed language that enabled you to convert an object into an array of objects without problem. Exploiting this powerful and flexible feature of MATLAB does introduce some organizational issues and may undermine your efforts at clean, object oriented code.
Problems begin because the MyBaseClass constructor is not a true constructor for MyBaseClass.
Wikipedia says:
"In object-oriented programming, a constructor (sometimes shortened to ctor) in a class is a special type of subroutine called at the creation of an object. It prepares the new object for use, often accepting parameters which the constructor uses to set any member variables required when the object is first created. It is called a constructor because it constructs the values of data members of the class."
Notice that the MyBaseClass constructor is not constructing values for the object members. Instead, it is a function that sets the object equal to an array of objects of type MyBaseClass and tries to set their data members to some value. You can see where the obj is destroyed at set to an array here:
obj(numel(arg)) = eval(class(obj));
This behavior is especially unhelpful when you derive MySubClass from MyBaseClass because MyBaseClass isn’t supposed to assign a new object to the variable obj----MySubClass has already created the new object in obj and is simply asking MyBaseClass to construct the portion of the existing object in obj that MyBaseClass knows the details for.
Some clarity might be gained by noting that when you enter the constructor for both MyBaseClass and MySubClass the variable obj is already populated with a perfectly good instance of the class. Good OOP practice would have you keep this original instance, use it in the base class constructor, and only act to populate its members in the constructor----not to overwrite the object entirely with something new.
My conclusion would be to not assign obj to be an array inside of MyBaseClass. Instead, I would recommend creating a class MyBaseClassArray that creates an array of MyBaseClass objects.
Unfortunately, you would also need to create a duplicate class MySubClassArray that creates an array of MySubClass objects. Languages like C++ and Java get around this code duplication issue with templates and generics, respectively but MATLAB does not currently support any form of templates (http://www.mathworks.com/help/techdoc/matlab_oop/brqzfut-1.html). Without templates there is no good way to avoid code duplication.
You could try and avoid some duplication by creating a generic CreateClassArray function that takes the string name of a class to create and the constructor arguments to use for each object---but now we are coming back to code that looks like your original. The only difference is now we have a clear division between the array class and the individual objects. The truth is that although MATLAB does not support templates, its flexible classes and typing system allow you use eval() like you have to change code and overwrite obj at will and create code that acts generically across classes. The cost? Readability, speed, and the uncomfortable feeling you got when you saw your base class constructing the subclass.
In short, you used MATLAB’s flexibility to overwrite the obj in the constructor with an array to avoid creating a separate container class for MyBaseClass. You then used eval to make up for not having a template feature in MATLAB that would allow you to reuse your array creation code all types. In the end, your solution is functional, reduces code duplication, but does require some unnatural behavior from your classes. It’s just a trade you have to make.

MATLAB - obtain the object a property belongs to?

Suppose I have a myClass < handle with property A. If I create an instance of myClass, say myObj, and pass myObj.A to a function, say function myFunc(val), is it possible within myFunc to see that the val passed to it is a property of myObj?
EDIT: For context:
I'm writing an API (in a sense) to interface with Arduino hardware for my research lab. The overarching class is called Vehicle, with properties PinManager < handle, TelemCollector < handle, and various Device < handles. It also has methods to do things like runMotor(), getAltitude(), etc. I have a method TelemCollector.telemFetch() which is the callback for a timer event; I would like TelemCollector.telemFetch() to be able to access Vehicle methods (namely getAltitude()); naively I would just make Vehicle a property of TelemCollector to access those methods. I was hoping to not have to do this.
EDIT2: Sample code snippet of what I'm trying to accomplish:
classdef Vehicle < handle
properties
PinManager
TelemCollector
Devices
end
methods
function obj = Vehicle(PM, TC, D)
obj.TC = TelemCollector();
obj.PM = PinManager();
obj.Devices = D();
end
function val = getAltitude(obj)
%# read altitude from a connected Device
end
function val = getSpeed(obj)
%# read speed from connected Device
end
end
end
classdef TelemCollector < handle
properties
%# ...
end
methods
function fetchTelem(obj)
%# do getAltitude(), getSpeed(), etc, here.. but I want to access
%# Vehicle.getAltitude() and Vehicle.getSpeed() somehow!
end
end
end
For all I know, no.
For example if myObj.A is a double, myFunc will just be passed the value it contains and there will be no reference to the object. If you were calling myFunc(somevariable) where somevariable was really the name of a variable and not an expression, then calling inputname(1) inside of myFunc would give you the string 'somevariable', but since you are referring to a property of a class, this is too complicated for MATLAB and inputname(1) just returns '' (tested with MATLAB R2011a).
Update: Why do you need to know this anyhow? If your interfaces are cleanly designed, you should probably not have to do this kind of thing. Or are you trying to work around someone else's bug/bad design? Depending on your application you could think of some kind of very dirty hack involving dbstack, trying to find out which m-file called your function, read the appropriate line of code from the .m file, parse it and then access the object using evalin('caller',...) ... but I doubt that's a good idea ;-).
Edit in response to context you provided:
Can't you just redefine your Timer callback to hand over the "Vehicle" object as well? i.e.
set(yourtimer_handle,'TimerFcn',{#fetchTelem,vehicle_handle});
means that whenever the callback timer calls the function TelemCollector.fetchTelem(), it hands over vehicle_handle as a third argument as described in the docu. This works in conjunction with a changed function head
function fetchTelem(obj, event, vehicle_handle)
where you can replace event by ~ in newer MATLAB versions if you don't need it.
Could that work?
fetchTelem can't call methods of an object that it doesn't have a reference to. So, regardless, you need to provide your TelemCollector object with the Vehicle handle.
Personally, I think the association between Vehicle and TelemCollector should be in the opposite direction. I would prefer something that looked more like:
V = Vehicle(PM, D);
TC = TelemCollector(V);
Although it really depends on how you expect to use the classes.
I agree with #Jonas Heidelberg: if it's this difficult, then it's probably the wrong interface.

Matlab subclassing question

Question about subclassing in matlab, under the new class system. I've got class A with some protected properties:
classdef Table < Base
properties (SetAccess = protected, GetAccess = public)
PropA = [];
end %properties
I'd like to make a subclass with some specialized features, and further restrict access to PropA. (i.e. make get access private in the subclass). My first thought was:
classdef subTable < Table
...
methods (Access = private)
out = get.PropA(obj, value);
end %private methods
However, in the help it says: "You must define property access methods in a methods block that specifies no attributes." So much for that idea.
Any ideas?
I don't believe this is possible. From MATLAB Documentation:
There are only two conditions that allow you to redefine superclass properties:
The superclass property Abstract attribute is set to true
The superclass property has both the SetAccess and GetAccess attributes set to private
Nor do I think that doing this would be a good idea. It violates the Liskov Substitution Principle. Functions written to accept a Table should also be able to accept a subTable and work properly. If such a function accessed PropA, it would fail when passed a subTable.