Brethlosze
Brethlosze

Reputation: 1612

Methods from Class Arrays

I have several classes with a lot of methods and functions, which normally handles mx1 arrays. For a given class:

S1.x=randn(m,1);
S1+2*randn(m,1); % Plus Override
S1.smooth; % Class Methods
S1.detrend; 

Now i wish to handle class arrays for the same given class, on a way like this;

S=[S1 S2 S3 S4];
S.smooth; % Methods for Class Array
S.detrend;

Question: Is there a simple way for doing this, without rewritting all the functions implementing the class properties and methods?

I am looking for some specific addition, redefinition, piece of code, trick, etc. in order to do that in a clean way. The purpose of this is code functionality, not performance -the few performance critical functions are already vectorized-.

Greetings,

Upvotes: 2

Views: 59

Answers (1)

gregswiss
gregswiss

Reputation: 1456

How about that:

classdef TestClass
   methods
       function smooth(obj)
           if numel(obj) == 1
               disp('Hello')
           else
               for i=1:numel(obj)
                   obj(i).smooth;
               end
           end

       end
   end
end

Called as follow:

>> t1 = TestClass;
>> t1.smooth
Hello


>> t2 = [TestClass TestClass TestClass];    
>> t2.smooth
Hello
Hello
Hello

If you really wanted to you should also be able to overload the subsref operator to automatically do that on all your methods (it gives you access to the . operator) . However in my experience overloading subsref correctly is not straight forward and might be more effort than what is worth.

Here is an example of this idea. It's simplistic and you will likely will need further refinement on your part but should get you started. Note the cheer amount of hackery :)

classdef TestClass
properties
    Value
end

methods        
    function obj = TestClass(x)
        obj.Value = x;
    end

    function smooth(obj)
        fprintf('I am %d\n', obj.Value)
    end

    function res = opposite(obj)
        res = -obj.Value;
    end

    function [res1,res2,res3] = test(obj)
        res1 = obj.Value;
        res2 = res1*res1;
        res3 = res2*res1;
    end

    function varargout = subsref(A,S)
        if numel(A) > 1 && strcmp(S(1).type, '.')
            if nargout == 0
                feval(S.subs, A(1));
            else
                nout = nargout(['TestClass>TestClass.' S.subs]);
                if nout < 0
                    nout = -nout;
                end
                if nout == 0
                    arrayfun(@(x)feval(S.subs, x), A);
                    varargout = cell(1, nargout);
                else
                    for i=1:nargout                            
                        [output{1:nout}] = feval(S.subs, A(i));
                        varargout{i} = output;
                        output = {};
                    end
                end

            end
        else
            if nargout == 0
                builtin('subsref', A, S);
            else
                varargout{:} = builtin('subsref', A, S);
            end
        end
    end        
end

Example of use:

>> t1 = TestClass(5);
>> t1.smooth;
I am 5

>> t2 = [TestClass(1) TestClass(2) TestClass(3)];
>> t2(2).smooth;
I am 2
>> t2.smooth;
I am 1
I am 2
I am 3
>> t2(1:2).smooth
I am 1
I am 2
>> t2(2:3).smooth
I am 2
I am 3
>> t2([1 3]).smooth
I am 1
I am 3
>> t2.test

ans = 

    [1]    [1]    [1]


ans = 

    [2]    [4]    [8]


ans = 

    [3]    [9]    [27]

Upvotes: 2

Related Questions