I recently consulted to a very large industrial client. Following a merger/acquisition, the relevant R&D department had two development groups using different technologies: one group uses Matlab, the other does not. My client wanted both groups to use Matlab, something that would naturally please MathWorks.
Unfortunately, it turns out that a technical challenge was preventing this move: the other technology enabled data field names (identifiers) longer than Matlab’s namelengthmax=63 characters, and these names also sometimes contained illegal identifier characters, such as spaces or symbols. This prevented an easy code transition, indefinitely delaying the migration to Matlab.
Accessing improper fieldnames
I suggested to this client to use Matlab class objects that overloaded the subsref() and subsasgn() methods: the long original identifiers would be stored in some internal container (cell array or containers.Map etc.), and they would be accessed not directly (which would be impossible since they are not valid Matlab identifiers) but via the overloaded methods. Something along the following lines:
classdef ExtendedFieldsClass % The internal data implementation is not publicly exposed properties (Access = 'protected') props = containers.Map; end methods (Access = 'public', Hidden=true) % Overload property assignment function obj = subsasgn(obj, subStruct, value) if strcmp(subStruct.type,'.') try obj.props(subStruct.subs) = value; catch error('Could not assign "%s" property value', subStruct.subs); end else % '()' or '{}' error('not supported'); end end % Overload property retrieval (referencing) function value = subsref(obj, subStruct) if strcmp(subStruct.type,'.') try value = obj.props(subStruct.subs); catch error('"%s" is not defined as a property', subStruct.subs); end else % '()' or '{}' error('not supported'); end end end end
This works splendidly, as the following snippet shows:
>> c = ExtendedFieldsClass c = ExtendedFieldsClass with no properties. >> c.(' asd f @#$^$%&') = -13.5; % no error >> c.(' asd f @#$^$%&') ans = -13.5 >> c.(' asd f @#$^$%& xyz') % note the extra "xyz" Error using ExtendedFieldsClass/subsref (line 27) " asd f @#$^$%& xyz" is not defined as a property
Note how we need to use the () parentheses in order to access the “properties” as dynamic fieldnames. We would naturally get an error if we tried to directly access the field:
>> c. asd f @#$^$%&
c. asd f @#$^$%&
|
Error: Unexpected MATLAB expression.
Tab completion
So far so good.
The problem is that we would also like to see the defined “properties” when in the desktop’s tab completion. i.e., when I type “c.” and then click <tab> in the Matlab command prompt, I’d like to see the list of defined “properties” in a tooltip (in the example above: ” asd f @#$^$%&”). Instead, I get the message “No Completions Found.”:

Missing tab completion
I described the hack for desktop tab-completion a few years ago. Unfortunately, that hack only works for functions. We need to find another solution for Matlab class objects.
The solution is to overload the fieldnames() function as well, such that it would return a cell-array of the relevant strings:
classdef ExtendedFieldsClass % The internal data implementation is not publicly exposed properties (Access = 'protected') props = containers.Map; end methods (Access = 'public', Hidden=true) % Overload property assignment function obj = subsasgn(obj, subStruct, value) ... (as above) end % Overload property retrieval (referencing) function value = subsref(obj, subStruct) ... (as above) end % Overload fieldnames retrieval function names = fieldnames(obj) names = sort(obj.props.keys); % return in sorted order end end end
When we now run this in the command prompt, we get the expected behavior:

Working tab completion
R2014a
Unfortunately, this works only up to and including Matlab release R2013b. In R2014a, MathWorks made some internal change that prevents overloading the fieldnames function. To be more precise, we can still overload it as above, and it will indeed work if we directly call fieldnames(c), but it no longer has any effect on the tab completion. On R2014a, the tab-completion remains broken and returns “No Completions Found.” When this was reported to MathWorks some time ago, the official response was that the previous behavior was considered a “bug”, and this was “fixed” in R2014a (don’t bother searching for it in the official bugs parade). Go figure…
So what do you think I should now do? Remember: this is a large client, who knows how many licenses are at stake. Should I suggest to my client not to switch to Matlab? Or should I suggest that they keep using R2013b across the entire organization and cancel their annual maintenance? Or maybe I should simply tell them to accept the fact that some important functionality should be expected to get broken whenever Matlab is upgraded?
I really want my client to switch to Matlab across the board. After all, as a Matlab consultant/trainer I directly benefit from a larger Matlab client-base. But these sort of things just blow me away. Sometimes I feel as if I am swimming against the current, and that’s frustrating. I admit it doesn’t happen very often. Then again, I guess if things were straight-forward, nobody would need me to consult them…
Don’t mind me – just blowing off some steam. I’m allowed to, every now and then, aren’t I?
Related odds and ends
Michal Kutil described a mechanism for overloading the methods function, which is also part of the tab-completion tooltip. The problem here is that we cannot simply overload methods in our class, since Matlab calls methods with the class name (not the class object reference) when it wants to determine the relevant methods to display in the tooltip. Michal’s solution was to create a wrapper function that calls the overloaded variant. This wrapper function can then be placed within a @char folder somewhere in the Matlab path. I used a similar trick for my profile_history utility last month.
Related newsgroup posts by Eric Salemi here and here.
Similarly, in order to overload the data-value tooltip (when hovering over the object in the editor), or when displaying the object in the Matlab command prompt, simply overload the disp() function (see related) – luckily, this still works in R2014a (I hope MathWorks won’t “fix” this “bug” in R2014b or whenever):
% Overload class object display function disp(obj) disp([obj.props.keys', obj.props.values']); % display as a cell-array end
This blog will now take a short vacation for a few weeks, due to my U.S. trip. I will return with some fresh material in August – stay tuned!
Related posts:
- Class object creation performance Performance aspects of Matlab class object creation are discussed, with specific suggestions. ...
- Setting class property types Matlab's class properties have a simple and effective mechanism for setting their type....
- getundoc – get undocumented object properties getundoc is a very simple utility that displays the hidden (undocumented) properties of a specified handle object....
- Accessing private object properties Private properties of Matlab class objects can be accessed (read and write) using some undocumented techniques. ...