Matlab: How to restict access to sub-class of abstract class method - matlab

Lets have a following three classes:
% Main class
classdef MjrClass < handle
properties (SetAccess = immutable, GetAccess = public)
cls;
end
methods (Access = public)
function self = MjrClass()
self.cls = SubClass(2);
end
end
end
% Abstract class
classdef (Abstract) AbsClass < handle
properties (SetAccess = immutable, GetAccess = protected)
p;
end
methods (Access = {?MjrClass})
function self = AbsClass(parent)
self.p = parent;
self.do();
end
end
methods (Access = public)
function show(self)
fprintf('self.p: %d\nself.c: %d\n', self.p, self.c)
end
end
end
% Sub-Class
classdef SubClass < AbsClass
properties (SetAccess = private, GetAccess = public)
c;
end
methods (Access = private)
function do(self)
self.c = self.p*2;
end
end
end
The logic is following. Main class MjrClass defines interface for end user. Inside, it creates (in general) several instances of SubClass class. Since those share some properties and methods they all inherit from AbsClass class. And because the AbsClass class alone has no purpose, it is defined as abstract class.
However as it is, Matlab complains it "Cannot access method 'AbsClass' in class 'AbsClass'". The problem is obviously the Access property of constructor method. But if I leave it public it does not reflect the fact that it shoould be instantiated only within MjrClass class.
The same problem applies to do() method of SubClass class, where Access = private should restrict the method to be called only once within the AbsClass constructor, not allowing user to call it.

The access specifier for the AbsClass constructor doesn't actually allow AbsClass to call that method. So, the fix is simple, allow AbsClass (and its subclasses) to call its own constructor, like this:
methods (Access = {?MjrClass, ?AbsClass})
function obj = AbsClass(...)
....

Related

How can I include a subclass definition file into an Octave class

I have two octave classes defined in the same directory:
/home/me/octave/#myclass/myclass.m
/home/me/octave/#mysubclass/mysubclass.m
mysubclass is a subclass of myclass:
mysubclass.m:
classdef mysubclass < handle
properties
my_property = 0;
endproperties
methods
function property = get()
property = my_property;
endfunction
endmethods
endclassdef
myclass.m:
classdef myclass < handle
properties
subclass = mysubclass();
endproperties
methods
function sub = get()
sub = subclass;
endfunction
endmethods
endclassdef
However I don't seem to be able to 'include' the subclass definition in the same way as I might for e.g. C++. I tried adding
addpath("../#mysubclass/");
at various points in myclass.m, but I get a syntax error.
Can someone help?

Access data in subclass from superclass

I have an object from my own class object that inherits from my own class data and my own class graphic in MATLAB. To represent the object object, it uses properties and methods from the data-superclass. Now I want to draw my object object with methods from the graphic-superclass, but the methods in this superclass don't know anything about its object-subclass.
Is there a way to give the required data, that is stored in the object-subclass, to the graphic-superclass without putting this information into a function argument like object.draw(this_data_stuff) with the method drawfrom the graphic-superclass and the data this_data_stuff from the object-subclass?
The only way I figured out is to store the subclass object object as property in the graphic-superclass, but it seems odd to store a subclass-object as property in a superclass-object, while the subclass inherits from the same superclass.
EDIT:
data-class:
classdef data < handle
properties
data_stuff
end
methods
function obj = data
end
function obj = compute(obj)
obj.data_stuff = ... % math
end
end
end
graphic-class:
classdef graphic < handle
properties
end
methods
function obj = graphic
end
function obj = draw(obj)
plot(obj.data_stuff,t) % ERROR, property 'data_stuff' is unknown
end
end
end
object-class:
classdef object < data & graphic
properties
end
methods
function obj = object
end
end
end
Test:
object_A = object; % creates object
object_A.compute; % generates data_stuff
object_A.draw; % draws data_stuff, Error here, because 'draw` needs access to the 'data_stuff'-property.

Nested Matlab Property listener

The property postSet of MATLAB handle classes are very handy, however I would be happy to be able to trigger nested classes separately. A minimal example with two nested classes for illustration:
classdef parentClass < handle
properties (SetObservable = true)
childClass
end
methods
function this = parentClass()
this.childClass = childClass();
end
end
end
and
classdef childClass < handle
properties (SetObservable = true)
value
end
methods
function this = childClass()
this.value = 0;
end
end
end
In the example script "runTest"
p = parentClass();
addlistener(p.childClass,'value','PostSet',#(o,e)disp('child value set'));
addlistener(p,'childClass','PostSet',#(o,e)disp('parent value set'));
p.childClass.value = 1;
The result is (as expected)
>> runTest
child value set
However, I am looking for an elegant way to detect the property change on both levels such that the result would be:
>> runTest
child value set
parent value set
One way to do this is to use the fact that the PostSet event gets triggered by default even when the previous and current values are the same. In the constructor of parentClass, we add a listener to the childClass's PostSet event, and the event handler only reassigns the childClass object:
classdef parentClass < handle
properties (SetObservable = true)
childClass
end
methods
function this = parentClass()
this.childClass = childClass();
addlistener(this.childClass,'value','PostSet', #this.handlePropEvent);
end
function handlePropEvent(this, src, event)
this.childClass = this.childClass;
end
end
end
Note that you would want to be more careful implementing this so that the event listener gets adequately disposed of (and reassigned) if the childClass property is assigned a different object.
In practice, childClass should probably implement its own event type which gets triggered by all property changes you're interested in, and parentClass only listens to that event.

MatLab OOP Setting a Property via a Utility Method

I'm trying to change a property in a class called houses via a utility method which is Static. I'm getting terribly confused with the reference obj as I don't know when and where it should be used. I am trying to bypass the constructor method so I can access the setProperty method, but I am getting errors such as too many output arguments. I've tried passing in obj as well as x, but I get similar errors. However, I can change the property a if I pass in a value to the constructor method.
classdef houses
properties
a;
end
methods
% constructor method
function obj = houses()
end
end
methods (Static)
function setProperty(x)
obj.a = x;
end
end
end
In general, you should not use static methods to set properties of a class. If your property is public, then you can use a static method but it is highly recommended that you do not. If your property is private/protected, then you definitely cannot use a static method to modify it.
Your class should look like this then (I took the liberty of stating explicitly the access properties of each block):
classdef houses
properties (Access = private)
a;
end
methods (Access = public)
% constructor method
function obj = houses()
end
function SetA(obj, a)
obj.a = a;
end
function DoSomething(obj, more_parameters)
% Lengthy stuff here
end
end
end
Now, regarding your question about obj: the answer is you must pass obj as the first argument of every instance method. The variable obj refers to the current instance of the class in a generic way. See for example the method DoSomething.
Static methods do not have access to any of the properties of the class, unless public. As such, when declaring a static method, you should not pass the obj variable.
Last thing: always use explicit access modifiers for your properties and methods. It will save you some headaches.
A static method is not typically supposed to access an object (hence it does not have access to obj).
If you want to modify a static propperty (shared by all objects, and the class itself), you can use something like:
classdef houses
properties (Static)
a;
end
methods
% constructor method
function obj = houses()
end
end
methods (Static)
function setProperty(x)
houses.a = x;
end
end
end
Regarding obj, it is the 1st argument of every methods (non static). So when you do:
o = myClass();
o.myMethod(args);
Matlab will see this as:
myMethod(o, args);
So when you define the method, you have to put obj as the 1st argument (in fact you can choose any name, it does not have to be obj).

Protected property is not accessible if defined as abstract

Using Matlab R2012a, I have the following class hierarchy:
classdef Parent < handle
properties (Abstract, SetAccess = protected)
Limit
end
end
classdef SimpleChild < Parent
properties (SetAccess = protected)
Limit = 1.0
end
end
classdef ExtendedChild < Parent
properties (Access = private)
Child = SimpleChild
end
properties (Dependent, SetAccess = protected)
Limit
end
methods
function this = ExtendedChild
this.Limit = 2;
end
function output = get.Limit(this)
output = this.Child.Limit;
end
function set.Limit(this,input)
this.Child.Limit = input;
end
end
end
This a simple example where the "Parent" class defines an abstract "Limit" property, which is implemented in both the "SimpleChild" and the "ExtendedChild" class. The "ExtendedChild" class encapsulates a private instance on the "SimpleChild" class and forward the access methods (get/set) to the private instance. Constructing an "ExtendedChild" instance fails with the following message:
>> obj = ExtendedChild
Setting the 'Limit' property of the 'SimpleChild' class is not allowed.
Error in ExtendedChild/set.Limit (line 16)
this.Child.Limit = input;
Error in ExtendedChild (line 10)
this.Limit = 2;
I would have expected the "Limit" property to be settable since it is defined in the "Parent" class with a protected SetAccess. I can make the problem disappear if the property is implemented directly in the "Parent" class, but then I cannot redefine it as dependent in the "ExtendedChild" class, which is the point of the construction (separation of interface and implementation).
Can someone tell me if I'm doing something wrong?
Since the Limit property of SimpleChild is protected, you can only set its value from SimpleChild or a subclass of SimpleChild, which is not the case for ExtendedChild.
I'm not entirely sure what you're trying to achieve, so can't really advise on what the "best" way to do it might be. But I would guess that whatever you want, it's unlikely that having a set method for a Dependent property is the right way to achieve it - there are only very rare reasons why you might want to do that.