Tom Heine
Tom Heine

Reputation: 33

Passing varargin to nested class method in MATLAB

I would like to parse variable inputs for several class methods in the same way, so I wrote a method to do just that and intend to call it from the other methods as needed. However, when I call methodB from methodA, varargin{:} isn't being passed as its cell contents but as another cell array – similar to if I hadn't included the {:}.

Does anyone have an idea why the contents aren't passing?

methods
    function varargout = methodA(obj,varargin)
        [obj,t.start,t.stop,prn,elevLim,t.interval] = methodB(varargin{:});
    end

    function varargout = methodB(varargin)
        % parse inputs here...

        %output parsed inputs to calling function
        varargout = {obj,t.start,t.stop,prn,elevLim,t.interval};
    end
end

Upvotes: 2

Views: 1305

Answers (1)

Matt
Matt

Reputation: 13973

When you try to use your code as stated in the question, you will get error messages which would have been valuable to mention. In case you write methodB(varargin) this message is:

Undefined function 'methodB' for input arguments of type 'double'.

And when writing methodB(varargin{:}) it is:

Undefined function 'methodB' for input arguments of type 'cell'.

The main problem here is that you have not explicitly defined the first argument of methodB to be an object variable. This is needed since methodB is a so-called ordinary method because it is not defined as static. There are some other problems in the code as well. For example methodA never assigns something to varargout and methodB should return obj which is not defined neither.


Solution with ordinary method

  • methodB needs to have an explicitly defined object variable, so the first line of the definitition should be: function varargout = methodB(obj,varargin). However, if we don't need obj in the method itself, we can replace it with ~, so it dosen't get assigned to a variable.
  • In order to call the method you need to use the proper syntax to call it, either methodB(obj,varargin{:}) or obj.methodB(varargin{:}).

Here is working code to verify it:

classdef nestedvarargin

    properties
    end

    methods
        function varargout = methodA(obj,varargin)
              [t.start,t.stop,prn,elevLim,t.interval] = methodB(obj,varargin{:}); % call ordinary method (syntax 1)
%             [t.start,t.stop,prn,elevLim,t.interval] = obj.methodB(varargin{:}); % call ordinary method (syntax 2)
            varargout = {t.start,t.stop,prn,elevLim,t.interval};
        end
        function varargout = methodB(~,varargin)
            % extract desired values from varargin (for example leave 3rd argument out)
            varargout = {varargin{1},varargin{2},varargin{4},varargin{5},varargin{6}};
        end
    end

end

Solution with static method

  • The other way is to define methodB to be static and call it as baseclass.methodB(varargin{:}). In this case, no explicitly defined object variable is needed.

The code looks like this:

classdef nestedvarargin

    properties
    end

    methods
        function varargout = methodA(obj,varargin)
            [t.start,t.stop,prn,elevLim,t.interval] = nestedvarargin.methodB(varargin{:}); % call static method
            varargout = {t.start,t.stop,prn,elevLim,t.interval};
        end
    end

    methods(Static)
        function varargout = methodB(varargin)
            % extract desired values from varargin (for example leave 3rd argument out)
            varargout = {varargin{1},varargin{2},varargin{4},varargin{5},varargin{6}};
        end
    end

end

Testing

In order to verify the functionality, you can use the following two lines. As defined in methodB, the third argument should be omitted as well as the arguments after the sixth (5 in the case below).

testobj = nestedvarargin;
[a,b,c,d,e] = testobj.methodA(1,2,[],3,4,5,[])

The output is be as expected:

a =
     1
b =
     2
c =
     3
d =
     4
e =
     5

Upvotes: 3

Related Questions