Inheriting from Sealed classes in MATLAB
Asked Answered
G

1

7

In MATLAB, one of the attributes of a class (defined after classdef) is Sealed, which means that no class can use it as a superclass (or to be more precise, "to indicate that these classes have not been designed to support subclasses."1).

For example, if I try to instantiate a class that's defined as below (considering table is Sealed):

classdef SomeLie < table

end

I would get the 'MATLAB:class:sealed' error:

>> A = SomeLie;
Error using SomeLie
Class 'table' is Sealed and may not be used as a superclass.

As I refuse to be told by a machine what I may or may not do, I would like to subclass a Sealed class, regardless. How can I do that in MATLAB R2017a?

I'm having a hard time believing that this system is completely airtight, so I'm looking for a solution that would cause the Sealed attribute to be silently ignored (or something of that sort). The desired solution should work without modifying any "library class definitions" to remove Sealed from them.


I tried playing around with "reflection", but arrived at a dead end...

classdef SomeLie % < table  
  properties (Access = private)
    innerTable table;
  end

  properties (GetAccess = public)
    methodHandles struct = struct();
  end

  methods    
    function slObj = SomeLie(varargin)
      slObj.innerTable = table(varargin{:});
%     methodHandles = methods(slObj.innerTable);
      ml = ?table; ml = {ml.MethodList.Name}.';
      ml = setdiff(ml,'end');
      tmpStruct = struct;
      for indM = 1:numel(ml)
        tmpStruct.(ml{indM}) = str2func([...
          '@(varargin)' ml{indM} '(slObj.innerTable,varargin{:})']);
      end
      slObj.methodHandles = tmpStruct;
    end

    function varargout = subsref(slObj,varargin)
      S = struct(slObj);
      varargout{:} = S.methodHandles.(varargin{1}.subs)(varargin{:});      
    end
  end

end

(There's no need to fix the above code, I was just sharing)

Govern answered 30/3, 2017 at 12:44 Comment(0)
K
0

I do not think the machine is the problem, but the class designer and he certainly has good motivations to seal the class. "Philosophy" of coding, a part, you could 'own' the class in a wrapper class without defining it sealed.

For example, supposer the class Hello is sealed and has a method (or function, if you wish) sayHello which you would like to use in inherited classes you could define a class FreeHello (public) which contains an instance of Hello. At the constructor you build the corresponding Hello and then you define a sayHello method whose body simply calls your Hello instance and makes it execute the sayHello method (and returns the output, accordingly).

In order to 'open' the sealed class, you need to do these for all properties and public methods; of course you are still not capable of accessing private methods, but now you can subclass your wrapper class, as you wish.

Kahlil answered 30/10, 2017 at 20:11 Comment(3)
If you look closely, this is what the code in the 2nd part of the question is "doing"... it fetches handles to all methods of the class that is being extended, and then forwards invocations to the inner class.Govern
True and more general; in theory you could define a function returning a public object of a sealed item, the way you wrote it; so thumbs up. A small note; you should also include a similar mechanism for properties. Did you end up 'opening' the sealed class? Why did you want to do that, if I may ask?Kahlil
I didn't finish that code because it didn't really work (can't remember exactly what was the issue). It's still unresolved seeing how there's no accepted answer :) This was asked mainly for education purposes, although, at the time, I might've tried modifying some functionality of table and didn't want to copy the entire class definition folder for something minor like that...Govern

© 2022 - 2024 — McMap. All rights reserved.