Is it a good idea to overload subsref to mimic MATLAB's griddedInterpolant behavior?

1 view (last 30 days)
As you know, griddedInterpolant and scatteredInterpolant create an interpolant object (say, F) that can be used to interpolate data by simply calling it as
Vq = F(Xq)
I was trying to reproduce the same behavior with a custom class. For example, let's say I want to create a quadraticPoly object that can be created with
F = quadraticPoly(x_data, y_data)
and then evaluated as Vq = F(Xq), rather than using a dedicated method such as Vq = F.evaluate(Xq).
How would one do that? The only thing that comes to my mind is to overload subsref as in my example implementation below, which seems to work.
However, I wonder if this is a good idea. Skimming trough the documentation, it just doesn't look like subsref was designed to be used like this. Is there a better way to do this? And in case there is no good way to do this and this is simply a bad idea, then how and why do griddedInterpolant and scatteredInterpolant work?
Example class usage:
F = quadraticPoly([0:0.1:2], [0:0.1:2].^2);
F([1.5 2; 1 0])
Example class:
classdef quadraticPoly
properties
xData
coefs
end
methods
function obj = quadraticPoly(x, y)
obj.xData = x;
obj.coefs = polyfit(x,y,2);
end
function res = subsref(obj, x)
if length(x) > 1
error("AAAH")
end
switch x(1).type
case '()'
res = polyvalm(obj.coefs, x(1).subs{1});
case '.'
error('MYDataClass:subsref',...
'Not a supported subscripted reference')
case '{}'
error('MYDataClass:subsref',...
'Not a supported subscripted reference')
end
end
end
end

Accepted Answer

James Lebak
James Lebak on 8 Mar 2022
Subsref is the way that griddedInterpolant does this. Another way is to inherit from matlab.mixin.indexing.RedefinesParen, or from matlab.mixin.Scalar. In either of the latter cases you redefine parenReference to do the function call (where you call it in the '()' case inside subsref now).
@Sean de Wolski correctly points out reasons why you might not want to do this by overloading indexing, and those reasons apply to both approaches.

More Answers (1)

Sean de Wolski
Sean de Wolski on 8 Mar 2022
Edited: Sean de Wolski on 8 Mar 2022
Personally, i.e. not speaking for my corporate overlords, I don't like this design pattern. I prefer a well-named "evaluate" method (e.g. for griddedInterpolant, an interpolate method) that takes the object as input and does whatever with it. A few reasons why:
  • I think this is clearer and easier to learn. Going back to college and learning fit() objects was painful. I remember taking while to figure it out even now 13 years later. interpolate(gi, x) is much clearer than gi(x).
  • Overloading indexing is slower for many things than function or method invocation.
  • You can't have object arrays unless you put a lot of effort into it. E.g. rather have an array of interpolant objects and be able to call interpolate(gi(3), x).
  • No tab-complete.

Tags

Community Treasure Hunt

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

Start Hunting!