Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

To resolve issues starting MATLAB on Mac OS X 10.10 (Yosemite) visit: http://www.mathworks.com/matlabcentral/answers/159016

Is it possible to dynamically add methods to an object, or to build a generic method that "catches attempts to access nonexistent methods"?

Asked by Cedric Wannaz on 16 Jan 2013

Dear all,

I have seen similar questions asked serveral times, e.g. here @mathworks and here @stackoverflow, but it never really applies to my context.

Hence my question: is it possible to do one of the following operations (?)

  • Add methods to an object dynamically during instantiation (from the constructor).
  • "Catch attempts to access a nonexistent method" by overloading some method (the way we overload subsasgn()/subsref() for managing indexing).
  • Subclass a given class dynamically, during instantiation (from the constructor). [I am a little less interested in this one, because we cannot subclass all built-ins].

The reason is the following. I built a class that allows users to "extend" existing objects passed to the constructor. To illustrate

 >> a = 2 ;                 % double
 >> b = MyClass( a ) ;      % double extended

Now I would like to "delegate" whatever method call to double if it is not implemented in MyClass. I can easily manage two situations, that I illustrate with a sin() function/method:

  1. I implement sin() in MyClass, so any sin(b) or b.sin() calls MyClass.sin() which can manage to apply sin() to the double 2. This is not a practicable solution in my case, because I cannot implement all possible methods for all possible "classes-to-extend".
  2. Without implementing MyClass.sin(), I can catch such calls with subsref() and manage the rest. This is again not a working solution, because sin(b) is not caught by subsref(). It seems actually that MATLAB tests whether MyClass/b has a sin() method when we evaluate sin(b) and returns an error if not, instead of trying the call and failing.. (?)

So is there a way to catch sin(b) with a subsref()-like method/overload, or a way to have MATLAB calling a specific method of MyClass/b when calls to nonexistent methods (or tests of existence) are attempted?

Thank you and best regards,

Cedric

0 Comments

Cedric Wannaz

Products

3 Answers

Answer by Matt J on 16 Jan 2013
Accepted answer

No, I don't think it's possible. But I put in an enhancement request for it several years ago.

2 Comments

Cedric Wannaz on 17 Jan 2013

Thank you Matt, I will wait a day to see if I can gather more information in the thread, but I fear that your answer will be the final word to this story/question.

Cedric Wannaz on 17 Jan 2013

I just put an enhancement request (with a few corrections):

-------------------------------------------------------------------------

As explained here: < link to this thread > some of us could use a mechanism for adding dynamically methods to objects.

Rational: assume x=MyClass(), with MyClass a user-define class. If a method MyClass.cos() is present, both calls x.cos() and cos(x) will call it. If we [implement the] overload MyClass.subsref(), we can manage calls like x.cos() whether MyClass.cos() exists or not. We can however not catch and manage calls like cos(x). It seems indeed that MATLAB "tests for the existence of x.cos() and returns an error if nonexistent", instead of "trying the call and returning an error if nonexistent". If there were no real argument in favor of the first behavior over the second, then the second would have the tremendous advantage that it could be caught. This way cos(x) and x.cos() could be both managed by our overload of subsref(). This would bring flexibility, consistency, and open new possibilities for developing powerful user-defined classes/types.

Matt J
Answer by Daniel on 17 Jan 2013

Probably not optimal, but you might be able to dynamically overload what classname returns, which in turn may affect what is called. I tried this in this answer:

http://www.mathworks.co.uk/matlabcentral/answers/45496-how-can-i-make-variable-editor-show-the-value-of-a-class-object-derived-from-double

There is also an answer by Malcolm that might be helpful.

1 Comment

Cedric Wannaz on 17 Jan 2013

Thank you! It doesn't solve my problem, but it is a very nice thing to have in mind, and that might be useful at one point to me.

It fools in fact quite a few things (whos, etc), but it doesn't prevent MATLAB from testing the existence of a method in the correct class

 >> x = MyClass(2) ;    % With the overload of the class method.
 >> class(x)
 ans = double
 >> a = x.cos()         % Caught with subsref overload and applied
 a = -0.4161            % to 'double' 2.
 >> a = cos(x)
 Undefined function 'cos' for input arguments of type 'MyClass'.
Daniel
Answer by Darik on 17 Jan 2013

It seems to work (in 2012b, at least) if you subclass dynamicprops

%
classdef MyClass < dynamicprops
    properties
        Data
  end
  methods
      function self = MyClass (x)
          self = self@dynamicprops;
            self.Data = x;
        end
        function varargout = subsref (self, S)
            try
                [varargout{1:nargout}] = builtin('subsref', self, S);
            catch
                [varargout{1:nargout}] = feval(S(1).subs, self.Data);
            end
        end
    end
end

>> a = MyClass(0);

>> a.Data %normal property access

ans = 0

>> a.my_method() %normal method call

ans = 100

>> a.cos() %overridden method call

ans = 1

1 Comment

Cedric Wannaz on 17 Jan 2013

Hi Darik, this works without subclassing dynamicprops indeed. What you cannot manage is cos(a), which will return an error message saying that there is no cos() function that supports MyClass arguments.

This shows that cos(a) is not strictly equivalent to a.cos(). The latter can be managed by subsref() (subs type = '.'), but cos(a) cannot. It is as if MATLAB, instead of trying the call a.cos(), were testing first the existence of the method cos() in MyClass/a and generating an error if nonexistent.

Darik

Contact us