How can I replicate {:} behaviour when overloading subsref in my class?

16 ビュー (過去 30 日間)
Arne
Arne 2018 年 11 月 29 日
回答済み: Guillaume 2018 年 11 月 29 日
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?

回答 (2 件)

Arne
Arne 2018 年 11 月 29 日
Well, I found a solution that works, although it feels a bit silly. Based on the discussion here, I also overloaded numArgumentsFromSubscript with its own builtin function (yeah...).
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()
function n = numArgumentsFromSubscript(obj, s, ic)
n = builtin('numArgumentsFromSubscript', obj, s, ic);
end
end
end
Now dummy.caData{:} works as exptected:
>> dummy.caData{:}
ans =
1 2 3
ans =
4 5 6
ans =
7 8 9
I'm leaving this question open for now though, just in case someone has a nicer solution that doesn't feel like a hack.

Guillaume
Guillaume 2018 年 11 月 29 日
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?

カテゴリ

Help Center および File ExchangeCustomize Object Indexing についてさらに検索

タグ

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by