MATLAB: overriding table() methods

别说谁变了你拦得住时间么 提交于 2019-12-01 15:44:21

After experimenting with several alternatives, I adopted the solution that intereferes the least with Matlab's native @table implementation and it's easily removed if things go awry.

The solution:

  • copy the whole @table folder, i.e. fullfile(matlabroot,'toolbox','matlab','datatypes','@table'), into a destination where you have write permissions.

    I picked the destination to be fullfile(matlabroot,'toolbox','local','myfiles') since I do not have to bother with OS cross-compatibility, i.e. matlabroot takes care of that for me.

  • paste into the destination your @table folder with the new, overloaded and overriding methods (partially overwriting the copied original files)

  • add the destination to the matlab path, before the original @table, e.g. addpath your_destination -begin

Effects, pros and cons:

  • The native @table class/methods are now shadowed, try e.g. which table -all. However, this effect is quite clear, easily detectable and easily removed (delete destintation and remove path);
  • No weird conflicts between native @table (now shadowed) and new @table;
  • All methods, new and old, are visible, try methods(table);
  • Private table methods are accessible...
  • ... but you are forced to use them.
  • Exposing the new methods (user-implemented) to the private ones requires more maintenance and direct handling of version conflicts in the table implementations.
  • You need write permissions on some eligible destination.

For those interested about the details, you can look into, https://github.com/okomarov/tableutils. Specifically the install_tableutils (the readme might not be updated).

The following works for me:

  1. Define a modified disp function, say disp_modified.m, as follows, and put it in your path:

    function disp_modified(t)
    if istable(t)
        %// Do whatever you want to display tables
        builtin('disp', '''disp'' function intercepted!')
    else
        %// For non-tables, call `disp` normally
        builtin('disp', t)
    end
    
  2. Define disp as a function handle to the modifed function (you can do that in startup.m to always have it by default):

    disp = @disp_modified;
    

After this, in the command window I get

>> disp(1:5)
     1     2     3     4     5
>> disp({1 2 3 'bb'})
    [1]    [2]    [3]    'bb'
>> disp(table(rand(1e3,1)))
'disp' function intercepted!

Depending on the usage of the new class perhaps you could follow a cleaner approach. The proposed approach described in your post has the drawback that perhaps code used in your updated environment would not be easily portable to a new environment, or a program executed in your environment may demonstrate different behavior in a different environment.

Some questions you could consider (and perhaps clarify) would be: How do you intend to use the new class? Do you want to replace all the existing table uses? Do you want to be able to use it instead of a table class argument? Or do you want to alter the table so that each usage of the original table class in your environment uses the new class.

If you just need a new improved table for your usage, you could consider encapsulating the original table class in a new class. E.g MyTable, delegate all the methods you do not need to the original table methods, replace the methods you would like to improve or add new ones.

Update: Just saw the complete solution in Github and understood what you intended to do. Nice work. I will leave the post in case anyone finds it useful.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!