Search code examples
matlaboopsubclass

Matlab: How to restict access to sub-class of abstract class method


Lets have a following three classes:

% Main class
classdef MjrClass < handle

   properties (SetAccess = immutable, GetAccess = public)
      cls;
   end

   methods (Access = public)
      function self = MjrClass()
         self.cls = SubClass(2);
      end
   end

end
% Abstract class
classdef (Abstract) AbsClass < handle

   properties (SetAccess = immutable, GetAccess = protected)
      p;
   end

   methods (Access = {?MjrClass})
      function self = AbsClass(parent)
         self.p = parent;
         self.do();
      end
   end

   methods (Access = public)
      function show(self)
         fprintf('self.p: %d\nself.c: %d\n', self.p, self.c)
      end
   end

end
% Sub-Class
classdef SubClass < AbsClass

   properties (SetAccess = private, GetAccess = public)
      c;
   end

   methods (Access = private)
      function do(self)
         self.c = self.p*2;
      end
   end

end

The logic is following. Main class MjrClass defines interface for end user. Inside, it creates (in general) several instances of SubClass class. Since those share some properties and methods they all inherit from AbsClass class. And because the AbsClass class alone has no purpose, it is defined as abstract class.

However as it is, Matlab complains it "Cannot access method 'AbsClass' in class 'AbsClass'". The problem is obviously the Access property of constructor method. But if I leave it public it does not reflect the fact that it shoould be instantiated only within MjrClass class.

The same problem applies to do() method of SubClass class, where Access = private should restrict the method to be called only once within the AbsClass constructor, not allowing user to call it.


Solution

  • The access specifier for the AbsClass constructor doesn't actually allow AbsClass to call that method. So, the fix is simple, allow AbsClass (and its subclasses) to call its own constructor, like this:

    methods (Access = {?MjrClass, ?AbsClass})
        function obj = AbsClass(...)
         ....