0

I wish to add a method called nansubset to the table class. Essentially it allows you to call T(r,c) where r and c are real positive integer vectors possibly containing NaN's.

Stubbed code for nansubset.m could be:

function T = nansubset(T, r, c)
T = T(r,c);
end    

I am following the instructions here, which detail how to add a new method to the cell class. Basically, in a folder on my Matlab path, I create a folder called @table, and within this folder, create a file called nansubset.m.

I am getting the following problems:

>> tmpT = table(); nansubset(tmpT, 1, 1)
Undefined function 'nansubset' for input arguments of type 'table'.

and

>> doc @table/nansubset
Your search - @table/nansubset - did not match any documents.

However:

edit nansubset

and

edit @table/nansubset

both open the method file in my editor.

Further, I followed the instructions in the above link to add the plus method to the cell class and find that it works perfectly.

Can someone please explain to me how I can add this additional method to the table class?

Community
  • 1
  • 1
Alex
  • 15,186
  • 15
  • 73
  • 127
  • I restarted my matlab session and got this: `Error using table/nansubset Previously accessible file "C:\Program Files\MATLAB\R2015b\toolbox\matlab\datatypes\@table\nansubset.m" is now inaccessible.` This was after I moved the `nansubset.m` file onto my matlab path as a stand alone function as suggested by @TroyHaskin. – Alex Jan 05 '16 at 05:24

1 Answers1

3

With the release of Matlab R2012b (version 8), the class folder behavior changed (emphasis is mine):

In MATLAB Versions 5 through 7, class folders do not shadow other class folders having the same name, but residing in later path folders. Instead, the class the combination of methods from all class folders having the same name define the class. This is no longer true.

For backward compatibility, classes defined in class folders always take precedence over functions and scripts having the same name, even those that come before them on the path.

The combination of the two bold statements explains the behavior:

  • cell is a built-in Matlab function that predates the new OOP rules that returns an instance of its class. And before R2012b, adding methods to a class folder called @cell added the methods to the object returned from the cell function (which isn't defined with a classdef nor a class folder); this ability was retained for compatibility with legacy user code.
  • table was added after R2012b, is defined via a class folder, and is Sealed. Since it is Sealed, it cannot be subclassed. And with the new rules, any @table folder without an associated classdef file will not register as a class folder nor will its methods be composed into the existing class unless it is part of the legacy system (like cell).

I can see three workarounds listed in the order I think is best:

  1. Have a function on the Matlab path, just like the one you have, and always call the "method" using function notation instead of dot notation. If you need more "methods" group them in a folder or package (if good namespacing is desired) on the path. Since table is a value class, this option doesn't seem bad.
  2. Create a wrapper class like the one below. It is cumbersome but automatically encapsulates the additional functions.

    classdef MyTable < handle
    
        properties
            tab;
        end
    
        methods
            function mytab = MyTable(varargin)
                mytab.tab = table(varargin{:});
            end
            function tabnan = nansubset(mytab,r,c)
                tabnan = mytab.tab(r,c);
            end
        end  
    end
    
  3. Create a local copy of [matlabroot,'\toolbox\matlab\datatypes\@table\*'] and add the methods directly. I can't think of any huge drawbacks to this per se, but it feels weird copying internals like this.
TroyHaskin
  • 8,361
  • 3
  • 22
  • 22
  • 1
    wow, thank you very much for the investigation that led to this. Essentially as a workaround I I think I have implemented option 1) as you suggest. I add an extra line: `if istable(T); ...; end`, where the `...` represents the code to subset the table `T`. – Alex Jan 05 '16 at 02:27
  • Does this also imply that it is not possible to add a method to a native matlab class except using option 3? If I am understanding correctly, of your solutions only option 3) creates a `table` class containing the new method. (I also tried adding the nansubset.m file to `'\toolbox\matlab\datatypes\@table\*'` but that didn't work either). – Alex Jan 05 '16 at 02:36
  • @Alex I'd say it means that a built-in type `btype` introduced in or after the R2012b release will not have functions listed in the folder `@btype` added to its method list after creation. It works for `cell` and `struct` and such because those types predate R2012b by a lot. – TroyHaskin Jan 05 '16 at 02:43
  • does this not also mean that it is very convoluted (as per your answer) to add a new method to a built-in type introduced after R2012b? – Alex Jan 05 '16 at 02:47
  • 1
    @Alex For `Sealed` types/classes, yes. And after some experimenting, I'd make a local copy of `@table` and adjust it if you want to augment the class directly. Altering the version in the Matlab system folder appears to be very fickle and weird. Also, a local copy will allow you to fallback to the default class if ever needed. – TroyHaskin Jan 05 '16 at 03:33
  • I edited my Matlab system folder and broke something. Did you encounter something like this: http://stackoverflow.com/questions/34604835/how-to-reset-class-folder-to-native-state? – Alex Jan 05 '16 at 05:37