Effacer les filtres
Effacer les filtres

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

3 vues (au cours des 30 derniers jours)
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
function obj = quadraticPoly(x, y)
obj.xData = x;
obj.coefs = polyfit(x,y,2);
function res = subsref(obj, x)
if length(x) > 1
switch x(1).type
case '()'
res = polyvalm(obj.coefs, x(1).subs{1});
case '.'
'Not a supported subscripted reference')
case '{}'
'Not a supported subscripted reference')

Réponse acceptée

James Lebak
James Lebak le 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.

Plus de réponses (1)

Sean de Wolski
Sean de Wolski le 8 Mar 2022
Modifié(e) : Sean de Wolski le 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.


Community Treasure Hunt

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

Start Hunting!

Translated by