Reputation: 1351
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.
Upvotes: 3
Views: 183
Reputation: 30165
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
Upvotes: 4
Reputation: 11812
Only a half answer
I couldn't find the way to customise the display of the table
of object, but if you can get by by using arrays
of object there is a way, described in Customize Object Display for Classes.
For your example, you have to derive your class with: matlab.mixin.CustomDisplay
, then override the displayNonScalarObject
method:
classdef MyVal < matlab.mixin.CustomDisplay
properties
foo
end
methods
function self = MyVal(varargin)
if nargin > 0
self.foo = varargin{1};
end
end
end
methods (Access = protected)
function displayNonScalarObject(objAry)
dimStr = matlab.mixin.CustomDisplay.convertDimensionsToString(objAry);
cName = matlab.mixin.CustomDisplay.getClassNameForHeader(objAry);
headerStr = [dimStr,' ',cName,' members:'];
header = sprintf('%s\n',headerStr);
disp(header)
for ix = 1:length(objAry)
o = objAry(ix);
% OPTION 1:
% For a class with a sinle property, no need to call the
% big guns, just build your own display:
disp( [num2str(ix) ': foo = ' num2str(o.foo) ] ) ;
% OR OPTION 2: (comment option1 if you use this)
% If your class had multiple properties and you want to
% display several of them, use the MATLAB built-in functions:
% create a structure with the property names you need
% displayed:
% propList = struct('foo',o.foo,'prop2',o.prop2,'prop3',o.prop3);
% Then let MATLAB handle the display
% propgrp = matlab.mixin.util.PropertyGroup(propList);
% matlab.mixin.CustomDisplay.displayPropertyGroups(o,propgrp);
end
end
end
end
Now if you build an array of your class, the display will look like:
>> foo(1) = MyVal(1); foo(2) = MyVal(2);
>> foo
foo =
1x2 MyVal members:
1: foo = 1
2: foo = 2
Of course this is just an example and is highly customizable. Unfortunately, I couldn't find a way to make that work for table
objects.
Upvotes: 2