matlabmatlab-tablematlab-class

Representation of value class in table


If I have a value class like this:

classdef MyVal
    properties
        foo
    end
    methods 
        function self = MyVal(varargin)
            if nargin > 0
                self.foo = varargin{1};
            end
        end
    end
end

and use it in a table:

foo(1) = MyVal(1); foo(2) = MyVal(2);
t = table(foo')

the output is:

t =

  2×1 table

       Var1    
    ___________

    [1×1 MyVal]
    [1×1 MyVal]

Is there any method which has to be defined in MyVal (or any property of the table) which allows to change the representation of the value in the table? I do not want to convert the data passed to table since I'd like to retrieve instances of MyVal when I index in the table.


Solution

  • You could create a custom wrapper for table. This is slightly pokey because MATLAB doesn't let you inherit from the table class, but by overloading the subsref and subsasgn operators you can get most of the functionality anyway...

    I've included the class at the bottom of this answer since it's a bit long, usage would look like this:

    >> foo(1) = MyVal(1); foo(2) = MyVal(2);
    >> t = MyTable(foo') % Omitting the ";" calls our overloaded "disp" function
    t = 
        Var1
        ____
        1   
        2   
    

    You can also use this to extract the numeric data (i.e. the foo property alongside other data) by using t.numeric, although I suspect you will need to use table2array on this for use with uitable, as you would with a normal table.

    classdef MyTable
        properties ( Access = private )
            table_
        end
        properties ( Dependent = true )
            numeric
        end
        methods % Constructor and getter
            function obj = MyTable( varargin )
                % Store as a normal table internally
                obj.table_ = table( varargin{:} );
            end 
            function num = get.numeric( obj )
                % By calling obj.numeric, output the table but with MyVal
                % objects replaced by their "foo" property.
                % This could be passed into a uitable, and is used in disp()
                cls = varfun( @(x)isa(x,'MyVal'), obj.table_, 'OutputFormat', 'uniform' );
                num = obj.table_;
                for ii = find(cls)
                    num.(num.Properties.VariableNames{ii}) = [num.(num.Properties.VariableNames{ii}).foo].';
                end            
            end
        end
        methods % Overloaded to emulate table behaviour        
            function disp( obj )
                % Overload the disp function (also called when semi colon is
                % omitted) to output the numeric version of the table
                disp( obj.numeric );
            end
            % Overload subsref and subsasgn for table indexing
            function varargout = subsref( obj, s )
                [varargout{1:nargout}] = builtin( 'subsref', obj.table_, s );
            end
            function obj = subsasgn( obj, s, varargin )
                obj.table_ = builtin( 'subsasgn', obj.table_, s, varargin{:} );
            end    
            % Have to overload size and isa for workspace preview
            function sz = size( obj, varargin )
                sz = size( obj.table_, varargin{:} );
            end
            function b = isa( obj, varargin )
                % This is only OK to do because we overloaded subsref/subsasgn
                b = isa( obj.table_, varargin{:} );
            end        
        end
    end