Customize display of an enumeration class - matlab

I'd like to customize the display of an enumeration class using matlab.mixin.CustomDisplay.
If I have a regular (non-enumeration) class such as the following:
classdef test < handle & matlab.mixin.CustomDisplay
properties
value
end
methods
function obj = test(value)
obj.value = value;
end
end
methods (Access = protected)
function displayScalarObject(obj)
disp(['hello ', num2str(obj.value)])
end
end
end
then everything works fine - for example,
>> a = test(1)
a =
hello 1
But if I have an enumeration class such as the following (note the addition of the enumeration block):
classdef test < handle & matlab.mixin.CustomDisplay
properties
value
end
methods
function obj = test(value)
obj.value = value;
end
end
methods (Access = protected)
function displayScalarObject(obj)
disp(['hello ', num2str(obj.value)])
end
end
enumeration
enum1(1)
end
end
then the display is not customized - for example,
>> a = test.enum1
a =
enum1
Using the debugger, I can see that my displayScalarObject method is never called. Implementing other methods of matlab.mixin.CustomDisplay such as displayNonScalarObject and so on doesn't seem to help - these never get called either.
What's going on? Do disp and display work differently for enumeration classes, in such a way that anything that's overridden by matlab.mixin.CustomDisplay just gets ignored?
Is there a way to get a customized display with matlab.mixin.CustomDisplay, but using an enumeration class?
PS I am able to directly overload disp and/or display on an enumeration class that does not inherit from matlab.mixin.CustomDisplay, and this works fine. But I'm looking to use matlab.mixin.CustomDisplay if possible.

I'll answer my own question in case anyone else is interested.
The question was asked with reference to MATLAB R2014a. In R2014b, an additional note has been added to the documentation for matlab.mixin.CustomDisplay, making it explicit that it is not possible to use matlab.mixin.CustomDisplay to derive a custom display for enumeration classes, and suggesting that the best approach is to overload disp.

Related

Program in same OOP style as App Designer

I like the OO programming style that matlabs App Designer uses (or at least the way I'm using it). Now I'm wondering if I can use the same style in my "normal" matlab class.
What I have now:
classdef myClass
properties
myVar;
end
methods
function Main(obj)
obj.myVar = "a";
obj = DoSomething(obj);
disp(obj.myVar) % outputs "c"
end
function obj = DoSomething(obj)
if(obj.myVar == "a")
obj.myVar="c";
else
obj.myVar = "b";
end
end
end
end
Which can be called externally using:
myClassInst = myClass;
myClassInst.Main()
I would like to get rid of all the "obj = " in the classdef, as is possible in App Designer. So something that would look like this:
classdef myClass
properties
myVar;
end
methods
function Main(obj)
obj.myVar = "a";
DoSomething(obj); % Just call the function without "obj = "
disp(obj.myVar) % outputs "a" because I didn't overwrite obj
end
function DoSomething(obj)
if(obj.myVar == "a")
obj.myVar="c";
else
obj.myVar = "b";
end
end
end
end
The equivalent of this seems to work in App Designer. So it appears you can modify variables in a class (instance?) in App Designer, while also being able to access the modified variable without explicitly overwriting your old class instance.
I noticed App Designer has all methods an properties set to (Access = private), though I'm not sure that has anything to do with it. Of course if I set everything to private, then I can't access the Main() method from outside anymore.
So my question is, how can I program in "normal" matlab, the same way as is possible in App Designer?
EDIT:
The following works in App Designer (I left out the methods/properties for the GUI elements):
classdef tmp < matlab.apps.AppBase
properties (Access = private)
myVar; % Description
end
methods (Access = private)
function doSomething(app)
if app.myVar == "a"
app.myVar = "c";
else
app.myVar = "b";
end
end
end
% Callbacks that handle component events
methods (Access = private)
% Code that executes after component creation
function startupFcn(app)
app.myVar = "a";
doSomething(app);
disp(app.myVar); % outputs "c"
end
end
end
You definitely can! All you have to do is inherit from the handle class, as opposed to a value class which is the default for matlab. You can also define private and public methods as in other languages.
The only thing you have to do is:
classdef myclass < handle % this is how you inherit from base class
properties
public_property
end
properties (Access=private)
private_property
end
methods
function obj = myclass() % class constructor
...
end
function public_function()
...
end
end
methods (Access=private)
function private_function()
...
end
end
end
Now every time you pass an object of this class to a function, you are not passing it by value, you are passing by reference (as you might be used to from python) and modifying it's properties modifies them also in the original object.
You need to inherit (< at the top of the class) from a handle class
classdef myClass < handle
properties
var
end
methods
function obj = myClass( varargin )
% Constructor function, called automatically when object is created
end
function someFunction( obj )
obj.randomizeVar(); % Equivalent to randomizeVar( obj );
end
function randomizeVar( obj )
obj.var = rand();
end
end
end
See the documentation for the difference between a "handle" and "value" class:
A value class constructor returns an object that is associated with the variable to which it is assigned. If you reassign this variable, MATLABĀ® creates an independent copy of the original object. If you pass this variable to a function to modify it, the function must return the modified object as an output argument. For information on value-class behavior, see Avoid Unnecessary Copies of Data.
A handle class constructor returns a handle object that is a reference to the object created. You can assign the handle object to multiple variables or pass it to functions without causing MATLAB to make a copy of the original object. A function that modifies a handle object passed as an input argument does not need to return the object.
Moreover, if you edit matlab.apps.AppBase, the class which you app designer code inherits, you can see that the first line is
classdef AppBase < handle
So you are literally doing the same thing, without the AppBase middle-man.

Problem with implementing abstract property in Matlab

In Matlab (2017b) I'm trying to implement a superclass with a yet undefined abstract property.
classdef Class_Test1
properties (Abstract=true)
obj
end
end
Subclasses should then implement this property and restrict it to a certain class, e.g.:
classdef Class_Test2 < Class_Test1
properties
obj#double = 123;
end
end
a = Class_Test2; now throws an error:
The property 'obj' restriction defined in class 'Class_Test2' must match
the property definition in base class 'Class_Test1'.
Is there no way to specify the class / type of obj in the implementation of the abstract class or am I missing something?
In the end I would like obj to be abstract in Class_Test1 to implement several subclasses, which will hold objects of different classes in obj.
Any help appreciated ...
MATLAB classes are weird... or in any case very different from what you expect from a class if you've learnt about classes in any other programming language.
One aspect of MATLAB is that it's an interpreted language. Stuff is evaluated when executed, not when compiled. So code doesn't always need to make sense.
So, we can solve your issue like this:
classdef (Abstract) foo
methods
function c = getclass(in)
c = class(in.obj);
end
end
end
The function foo.getclass seems to not make sense, since foo doesn't have a property obj. But because foo is abstract, we're never going to have an object of class foo on which we'll call the getclass method. Whenever getclass is called, it'll be a derived class. So, if we want to use this getclass method, we need to make sure that the derived class has a property obj:
classdef foo_uint8 < foo
properties
obj#uint8 = uint8(1);
end
end
It is now possible to call foo_uint8.getclass:
>> a = foo_uint8;
>> a.getclass
ans =
'uint8'
OK, so after looking into this further it seems that this is a deliberate limitation based on the design of Matlab. I'm not too familiar with OOP in other languages but would be interested to learn if this is an general OOP fundamental or rather Matlab specific.
As a workaround I have come up with the following solution:
classdef (Abstract) Class_Test1 < handle
properties
Obj
end
properties (Abstract = true, Constant)
ObjClass#char
end
methods
function set.Obj(obj_in,in)
if isa(in, obj.ObjClass)
obj_in.Obj = in;
end
end
end
end
... and the implementation ...
classdef Class_Test2 < Class_Test1
properties (Constant)
ObjClass#char = 'double'; % Define the allowed class here ...
end
end
I would still be interested to learn about other possible solutions.

how to change value in map.continer child class

i have this superClass
classdef SysSignal<handle
%SIGNALP Summary of this class goes here
% Detailed explanation goes here
properties (SetAccess = public, GetAccess = public )
SetOfSignal = containers.Map('KeyType','char', 'ValueType', 'any')
end
methods
%constructor
function sys=SysSignal()
end
function sys=adds(sys,varargin)
%convert form cell to signalup
for n=1:length(varargin)
signal=varargin{1,n};
if isempty(signal.name)
continue
else
%add to the map
sys.SetOfSignal(signal.name)= signal;
end
end
end
and that child class
classdef Signalp<SysSignal
%SIGNALP Summary of this class goes here
% Detailed explanation goes here
properties
name
lineNo
color='red'
sumrole
end
properties (SetAccess=private,GetAccess=public)
arrPrice
LineLength
LineProportion
end
methods
%constructor
function sig=Signalp(varargin)
end
end
end
now i want to change the properties like this:
sys=SysSignal;
s=Signalp;
s.name='dd';
sys.adds(s)
sys.SetOfSignal('dd').sumrole='hello'
but i get that error :
??? Error using ==> subsasgn
Only one level of indexing is supported by a containers.Map.
how can i change the values from the superClass?
The answer is to seperate sys.SetOfSignal('dd').sumrole='hello' into two statements:
dd = sys.SetOfSignal('dd');
dd.sumrole='hello'
That is because sys.SetOfSignal('dd').sumrole doesn't do what you'd intuitively think it does. Indeed the containers.Map class overloads the subscripted reference and subscripted assignment operators. In essence they 'intercepts' the (), {} and . operators at the same time (ie .sumrole is 'sent' to the map.Containers object - instead of your object!). In my opinion that's a really weird design decision but we must live with it!
Have a look at these links for more info:
subsref, subsasgn
gregswiss's answer is correct, except that accessing the containers map creates a copy, so you finish by replacing the old value with the new modified one
dd = sys.SetOfSignal('dd');
dd.sumrole='hello'
sys.SetOfSignal('dd') = dd;

Matlab OOP code reusing

First of all, I belive I should say that I am a newbie on OOP in Matlab, but quite experenced with other languages like C++. So this question may sound like so easy to you but I somehow could not find an explanation to my problem.
Suppose that I have two classes, where the former one is an Abstract class and the latter one is a derived class which is derived from the abstract base class.
You can see an example below.
classdef (Abstract) queue < handle
properties
queue_array = [];
read_index =1;
end
methods
function insert_to_queue (obj, queue_element)
obj.queue_array = [obj.queue_array, queue_element];
end
function clean_queue (obj)
obj.queue_array = [];
obj.read_index = 1;
end
end
end
classdef fifo_queue < queue
properties
end
methods
function get_next_from_queue (obj)
...
end
end
end
Here as you can see, I put the common functions of all the derived classes to the base class for the purpose of code reuse.
However when I try a scrpt like below
f_que = fifo_queue;
f_que.instert_to_queue(some_data); % OK
f_que.clear_queue(); % Error
I got an error like;
No appropriate method, property, or field print for class fifo_queue
Do you have any idea of why I face with this type of behaviour on MATLAB?
Thanks

Is it possible to hide the methods inherited from the handle class in matlab?

I'm working on a command line application for ultrasound simulation in MATLAB. Nearly every object in our code is a subclass of handle (to pass as references). The problem I'm having is that all the methods inherited from the handle class shows up under the "Methods" section in MATLAB (see example below).
What I want is to hide the inherited methods from the handle class so that only the function the user is allowed to use is shown under "Methods". This way it doesn't look so messy for the user if he/she wants to know which methods to use.
Example Test class:
classdef Test < handle
methods
function myFunction(obj)
end
end
end
In the command line:
T = Test()
T =
Test handle with no properties.
Methods, Events, Superclasses
After clicking on "Methods":
Methods for class Test:
Test delete findobj ge isvalid lt ne
addlistener eq findprop gt le myFunction notify
What I want:
Methods for class Test:
Test myFunction
Is this possible in MATLAB?
If you overload all of the subclass methods in a hidden methods block I think it will do exactly what you're looking for.
I'm not sure which versions of Matlab this works in, but it definitely works for me in R2012b.
The exception is isvalid as it is Sealed so you can't override it in a handle subclass.
classdef handle_light < handle
methods(Hidden)
function lh = addlistener(varargin)
lh = addlistener#handle(varargin{:});
end
function notify(varargin)
notify#handle(varargin{:});
end
function delete(varargin)
delete#handle(varargin{:});
end
function Hmatch = findobj(varargin)
Hmatch = findobj#handle(varargin{:});
end
function p = findprop(varargin)
p = findprop#handle(varargin{:});
end
function TF = eq(varargin)
TF = eq#handle(varargin{:});
end
function TF = ne(varargin)
TF = ne#handle(varargin{:});
end
function TF = lt(varargin)
TF = lt#handle(varargin{:});
end
function TF = le(varargin)
TF = le#handle(varargin{:});
end
function TF = gt(varargin)
TF = gt#handle(varargin{:});
end
function TF = ge(varargin)
TF = ge#handle(varargin{:});
end
function TF = isvalid(varargin)
TF = isvalid#handle(varargin{:});
end
end
end
If you save the above class to handle_light.m and then type methods handle_light in the command window you will get the following result:
Methods for class handle_light:
handle_light isvalid
The Test class then becomes:
classdef Test < handle_light
methods
function myFunction(obj)
end
end
end
Doing it in this way means that you don't need to put the overloads in the Test class which keeps things neater.
There is a solution here, including sample code.
In short, what you need to do is to overload Matlab's built-in function methods, so that when it is called on your class, it removes the methods of handle from the output. Make sure it works on everything else, though so that you don't mess up your user's other code. If you don't use the #foldername variant to store your class, you could put it into a private directory, for example.
Not a full solution, but if you do methods(T, '-full'), then it at least tells you which methods are inherited from handle, so you know what to ignore.
Just get the functions from the inherited class and cancel them out with the ones from the main class using setdiff.
mH = methods('handle');
m = methods('MyClass');
m = setdiff(m,mH);