Overriding superclass methods and access modifiers in MATLAB - oop

Consider the following simple class hierarchy:
A.m
classdef A < handle
methods (Access = protected) %# protected vs. private
function foo(obj)
disp('class A')
end
end
end
B.m
classdef B < A
methods (Access = public)
function foo(obj)
disp('class B')
end
end
end
Class B inherits from class A and is supposed to override the protected foo method as public.
If we try to instantiate the derived class, we get the following error:
>> b=B();
Error using B
Method 'foo' in class 'B' uses different access permissions than its superclass 'A'.
The weird thing is if foo was defined as private method in the superclass A, the code works just fine when we invoke the overridden method:
>> clear classes
>> b=B(); b.foo()
class B
So is this a limitation/bug in MATLAB OOP implementation, or is there a good reason behind this behavior? (Code was tested on R2012b)
As a comparison, in Java the rules state that you cannot reduce visibility of a method in the sub-class, but you can increase it, where:
(weakest) private < package < protected < public (strongest)

This appears to be a limitation of Matlab. I've tried all combinations of attributes. Matlab throws errors whenever the attributes are different, except when the method of A is private, in which case the attributes in B don't matter.
In other words, unless the method in A is private, the attributes of the method in A and B have to be the same. I guess this does make sense to some extent, in that TMW say "If a method is visible to the subclass, attributes have to be the same; if a method is not visible to the subclass, the subclasses can do whatever they like".

Related

How to extend derived classes by defining class(es) that exposes the instance as a property

I have a class that I would like to extend by defining a new class that contains the first class as a public property, as well as additional added properties. However, the class that I'm extending has multiple derived types, which should be treated the same in the extension class.
Below is an example of what I am trying to do:
Public Class ClassA
End Class
Public Class ClassB
Inherits ClassA
End Class
Public Class ClassC
Inherits ClassA
End Class
Public Class BaseExtended
Public Property Foo As ClassA
Public Property ExtendedMetaData1 As Double
Public Property ExtendedMetaData12 As Integer
End Class
Public Class DerivedExtendedB
Inherits BaseExtended
Public Property Foo As ClassB
End Class
Public Class DerivedExtendedC
Inherits BaseExtended
Public Property Foo As ClassC
End Class
The code that uses an instance of any of the 'extended' classes would then need use that instance appropriately depending on it's type. There would be many cases where the property 'Foo' needs to be accessed and modified outside of the class that it belongs to.
If I were to implement something like what I have shown above, that would require that I first cast it to the required type before accessing or modifying it. Ideally I would like to do that inside the 'DerivedExtended' class; The alternative, I think, would be to duplicate code to cast that property would [hundreds of times] in the client code.
Private Sub ClientUsesObject(bar As BaseExtended)
' Perform a task that is agnostic Foo type
' Would not require that Foo be cast to any specific type
If bar.GetType() Is GetType(DerivedExtendedB) Then
Dim barCast As DerivedExtendedB = DirectCast(bar, DerivedExtendedB)
' Perform task that requires Foo to be of type ClassB
ElseIf bar.GetType() Is GetType(DerivedExtendedC) Then
Dim barCast As DerivedExtendedC = DirectCast(bar, DerivedExtendedC)
' Perform task that requires Foo to be of type ClassC
End If
End Sub
What I'm looking for is advice outlining or describing a design pattern that can handle this situation. I've searched for quite a while, and have not been able to find any examples that solve this problem.
I realize that this may be somewhat of an "XY" problem. I'm working with existing code that simply assumes all instances are of the same derived type (when in fact some instances are of the other derived type). As such, the existing code does not work. To me what I've tried to outline above seems like the most straightforward path, but I'm open to alternative if this is just the wrong approach.
This pattern of type covariance in derived classes is the canonical reason for what is called in C++ the "Curiously Recurring Template Pattern" and has been called in .NET the "Curiously Recurring Generic Pattern." I believe it's also sometimes referred to as "F-Bounded Polymorphism" (not a computer scientist, so I might have the reference wrong).
You can write a base class like this:
Public Class Base(Of TDerived As Base)
Public Overridable Property foo As TDerived
End Class
And then use it like this:
Public Class MyDerived
Inherits Base(Of MyDerived)
End Class
Then, the derived class has a property foo whose type is MyDerived. No casting required by clients.
However, this has some limitations. It works best when you don't need to switch back and forth between derived and base. There is no one Base, so you can't declare instances of it. If you want to be able to declare something as Base, then you end up needing to fall back on a non-generic base class. This will still work well for certain usage patterns where you don't need to convert from base to derived, but otherwise you run right back into the casting problems you are trying to avoid.
Eric Lippert has written a bit about this pattern. He's always interesting to read, so I'd recommend looking up his commentary.
Another alternative to consider, if the generic approach doesn't work for you, is code generation. You can use T4 templates to process a compact description of what your code should be, and generate the code files from them. A long list of casts is less tedious if you only write the machinery to generate it, you don't write them all out explicitly.

MATLAB OOP: Communication between objects of different subclasses

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.

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

"Public \ Friend" vs "Friend \ Friend"

I've been reading about access modifiers in VB.Net lately, and there is something that I can't really understand: How do elements in a Class (or Module) inherit the modifiers of their enclosing block?
For example, suppose you have a Friend class Bla in an assembly, with a public method Foo:
Friend Class Bla
Public Sub Foo
(...)
End Class
Does it behave differently than when Foo is set to Friend? If so, which one do you advise?
Friend Class Bla
Friend Sub Foo
(...)
End Class
Thanks!
In my opinion, it doesn't matter whether one specified public or Friend for Foo because the enclosing class is available only in this assembly.
One can choose to restrict the access modifier for a method/property than that of the class. In your example, the method Foo can be private` as well, which means the method won't be available to callers, including other classes in the same assembly.
One can access methods through class/instance. If the class is private, what use is a public method?
EDIT: On a side note, it is possible for you to return an instance of Bla to the caller (which is in other assembly). In that case, the caller should be able to call public method, if Foo is declared public. This is my assumption.
If someone does jump through the reflection hoops required to access Bla, they don't need to do so again to then call Public Sub Foo, but they do for Friend Sub Foo.

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.