How can I replicate {:} behaviour when overloading subsref in my class?
Afficher commentaires plus anciens
I have written a class that has a cell array property where the cells contain data that the object operates on.
classdef dummyClass < handle
properties(SetAccess = protected)
caData
end
methods
function this = dummyClass(caData)
this.caData = caData;
end
function customFunction(this, data)
% <Code that operates on caData>
end
function varargout = subsref(this, s)
if strcmp(s(1).type, '()') && length(s) == 1
% User called this(ind). This works as intended
this.customFunction(this.caData{s.subs{1}})
else
% Use standard indexing for any other case
[varargout{1:nargout}] = builtin('subsref', this, s);
end
end % subsref()
end
end
I overloaded subsref() in my class because I want a dummyClass object to execute customFunction() when I index into it like this:
caData = {[1 2 3], [4 5 6], [7 8 9]};
dummy = dummyClass(caData);
dummy(1) % dummy executes custom function on dummy.caData{1}
This works as intended.
I noticed, however, that dummy.caData{:} does not work as expected anymore. Usually, you would get a list of all cells like this:
>> caData{:}
ans =
1 2 3
ans =
4 5 6
ans =
7 8 9
But dummy.caData{:} yields this
>> dummy.caData{:}
ans =
1 2 3
This is in line with standard function behaviour in Matlab, because the number of returned outputs is driven by the number of outputs requested in the function call. Consequently, the following works as expected:
>> [c1, c2, c3] = dummy.caData{:}
c1 =
1 2 3
c2 =
4 5 6
c3 =
7 8 9
However, the documentation also states that the builtin subsref (which I'm calling in my code) is called whenever you index into an object. Yet the behaviour is clearly different in the two scenarios shown here. I still want to be able to do [dummy.caDummy{:}] to concatenate the contents of all cells, which is not possible as it stands. How do I replicate the normal {:} behaviour in my overloaded subsref?
Réponses (2)
Arne
le 29 Nov 2018
Guillaume
le 29 Nov 2018
I think it was a bad design decision of mathworks to use the same function for all types of indexing forcing you to handle even for those types where you just want the default behaviour.
As far as I can tell, for your class to work the same way as it would normally with . and {}, you would have to navigate the whole s struct array to figure out what each operation is going to return and overload numArgumentsFromSubscript so that nargout has the correct value when you receive a {xxx} index in your subsref. After having tried once to overload subsref for a class, I've given up. It's too fraught with peril. I use an explicit function myclass.at(xxx) or similar instead.
I certainly wouldn't override (). If you do, you also need to override cat, horzcat, vertcat, empty maybe, and possibly loadobj to prevent the creation of non-scalar objects of your class. Otherwise what should:
dummy = [dummyClass({[1 2 3]}), dummyClass({[4 5 6]})]
dummy(1)
do? Index the dummy array or invoke your custom function?
Catégories
En savoir plus sur Customize Object Indexing dans Centre d'aide et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!