MATLAB:覆盖table()方法

时间:2016-01-23 16:24:11

标签: matlab oop methods override

SETUP Win7 64b,R2015b,16 GB RAM,CPU i7-2700

table()是一个fundamental Matlab class,它也是密封的,因此我无法将其子类化。

我想修复此类的某些方法,添加新的方法。 例如,table.disp()从根本上被打破,例如尝试不disp(table(rand(1e7,1))),或忘记命令窗口中的;。该变量在RAM中仅占用76 MB,但显示器是无缓冲的,它会使系统失速!

  1. 我可以覆盖方法,例如table.disp(),而无需写入matlabroot\toolbox\matlab\datatypes\@table吗?
  2. 我可以使用C:\MATLAB\@table\ismatrixlike.m下的新方法扩展表类吗?我为什么要

    ismatrixlike(table)
    Undefined function 'ismatrixlike' for input arguments of type 'table'. 
    

    显然,我做了

    addpath C:\MATLAB\
    rehash toolboxcache
    

    我也试过clear all

    该路径具有(字母)优先于matlabroot的优先级,但缺少table.m类定义。如果我将本机类定义添加到C:\MATLAB\@table,那么我可以运行我的新方法(在clear all之后)。但是:

    >> methods(table)
    
    Methods for class table:
    
    classVarNames   ismatrixlike    table           varfun          
    convertColumn   renameVarNames  unstack      
    

    仅列出新\@table文件夹中的方法,即使(某些)旧方法仍然有效,例如。

    size(table)
    

    这部分解决了这个问题,因为现在,本机\@table\private文件夹不再可访问,因此许多本机方法都被破坏了!

  3. 为什么我这样做?因为在table()修复之前我不想再等待2年。我已经失去了整整一天,因为我在命令窗口中忘记了一个;,如果它正在运行多天模拟,我不能强行重启我的电脑,但我必须等待磁盘交换结束:(。

    附录 有关disp(table(rand(1e7,1)))的更多背景信息。当我点击它时会发生这种情况(幸运的是我的速度足够CTRL-C):

    enter image description here

    罪魁祸首是table.disp()的第172行,它将数值数组转换为单元格字符串(也使用填充!):

    [cells, err, isLeft] = sprintfc(f, x, b);
    

3 个答案:

答案 0 :(得分:3)

在尝试了几种替代方案之后,我采用了与Matlab的本地@table实现最少相关的解决方案,如果出现问题,它很容易被删除。

解决方案:

  • 将整个@table文件夹(即fullfile(matlabroot,'toolbox','matlab','datatypes','@table'))复制到您具有权限的目的地。

    我选择目标fullfile(matlabroot,'toolbox','local','myfiles'),因为我不需要为操作系统交叉兼容而烦恼,即matlabroot为我处理这个问题。

  • 使用新的,重载和重写方法
  • 粘贴目标您的@table文件夹中(部分覆盖复制的原始文件)

  • 目的地添加到原始@table之前的matlab路径,例如addpath your_destination -begin

效果,利弊:

  • 原生的@table类/方法现在已被遮蔽,例如尝试which table -all。但是,这种效果非常清晰,易于检测并且易于删除(删除目标和删除路径);
  • 原生@table(现已遮蔽)与新@table之间没有奇怪的冲突;
  • 所有方法,无论新旧,都可见,请尝试methods(table);
  • 可以访问私人表格方法......
  • ...但你被迫使用它们。
  • 将新方法(用户实现的)暴露给私有方法需要更多维护并直接处理表实现中的版本冲突。
  • 您需要对某些符合条件的目的地的写入权限。

对于那些对细节感兴趣的人,您可以查看https://github.com/okomarov/tableutils。具体来说,install_tableutils(自述文件可能不会更新)。

答案 1 :(得分:1)

以下适用于我:

  1. 定义修改后的disp函数,例如disp_modified.m,如下所示,并将其放在您的路径中:

    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. disp定义为修改后的函数的function handle(您可以在startup.m中执行此操作,以便始终默认使用它):

    disp = @disp_modified;
    
  3. 在此之后,在命令窗口中我得到

    >> 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!
    

答案 2 :(得分:0)

根据新课程的用法,您可以采用更清洁的方法。您的帖子中描述的建议方法的缺点是,更新后的环境中使用的代码可能无法轻松移植到新环境,或者在您的环境中执行的程序可能会在不同的环境中展示不同的行为。

您可以考虑(也许澄清)的一些问题是:您打算如何使用新课程?是否要替换所有现有的表用途?您是否希望能够使用它而不是表类参数?或者您是否要更改表,以便环境中原始表类的每次使用都使用新类。

如果您只需要一个新的改进表供您使用,您可以考虑将原始表类封装在一个新类中。例如,MyTable,将您不需要的所有方法委托给原始表方法,替换您想要改进的方法或添加新方法。

更新:刚看到Github中的完整解决方案,并了解您打算做什么。干得好。如果有人发现它有用,我会留下这个帖子。