How can I get a class property to be overridden and handled as a variable?

7 views (last 30 days)
Some of the Matlab classes have a great features, e.g. TABLE, by letting the class be called with a property that is really a variable inside the class.
For example:
somedata = {'a','b','c'}
T = table (somedata)
And you can then access the row of "a" by calling
T.a
and you can even call it with "modifiers", e.g.
T.a(end-1:end)
to get the last two rows
How can this be replicated in my own class definition / how does a class "capture" that this is not a real method/property, but to be treated as a variable? And how is the "end-1:end" command captured in this case so it can be used in the class?

Accepted Answer

Guillaume
Guillaume on 4 Jun 2019
There are various ways to customise properties such as dynamic properties.
However, what you're looking at here with table has nothing to do with customised or overriden properties. The T.xxx T{xxx, yyy} and T(xxx, yyy) syntax override the default indexing (subsref) and default assignment (subsasgn) methods. As for end, it is the end method that is overriden.
For example the line
T{end-1:end, 'a'}
is actually
  • two calls to end(T, 1)
  • a call to numArgumentsFromSubscript
  • finally a call to subsref(t, struct('type', '{}','subs', {[calculatedindex calculatedindex], 'a'})
The line
T.a(end-1:end)
is actually a call to
subsref(t, struct('type', '.', 'subs', {'a'});
followed by a plain matrix indexing.
You can do the same for your own class. It's all explained under Obejct Indexing. However, be aware that it's a lot of work to get right. You can actually see how it's implemented for tables. It's all in m files. The simples way is to use the debugger to step through a line that index a table. Or you can find the implementation of the overriding methods in
fullfile(matlabroot, 'toolbox\matlab\datatypes\@tabular')
  3 Comments
Guillaume
Guillaume on 4 Jun 2019
Personally, I don't bother. As you can see it's a complex machinery and I dislike the fact that even if you just want to override one type of indexing (e.g. {}) you lose the built-in indexing for the other two so have to reimplement () and . indexing yourself.
So I just implement my own indexing method,e g. myclass.at(index). Less headache.
Hakon Haugnes
Hakon Haugnes on 4 Jun 2019
Excellent advice and I agree with this approach until absolutely necessary to bite the bullet.
Maybe I can ask the following which then bugs me:
classdef class1 < handle
properties
data = [] %does not really matter
end
methods
function self = class1() %constructor
a=123; %does not matter
end
% some method that returns an array that we may want to index into as a chain
function v=mydata(arg1)
switch arg1
case 'a'
v = [1 2 3];
end
end
%some indexing method
function v=at(arg1)
fprintf('At');
disp(arg1)
end
end
end
I wonder if it is possible to chain class calls somehow like this?
c=class1;
c.v % Return the whole v array. Trivial. Works.
% Now can we return just part of v somehow in a single chain
% without invoking arguments on the call on v itself ?
% the problem is that v is just an array, not an instance of the class so doesn't have methods!
c.v(end) % this would work but I'd like to keep the argument for other things
c.v.at(end) % Separate index method, but this chaining does not work

Sign in to comment.

More Answers (0)

Categories

Find more on Loops and Conditional Statements in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!