Hide classes in Matlab similar to private functions - matlab

Private functions in Matlab are functions stored in a folder with the name "private" and they are only available to the functions immediately above this folder.
I tried the same for classes but Matlab 2016b refused with
A class definition may not be in or below a private directory.
I'm writing a toolbox and I want some internal classes not to be visible within Matlab itself, e.g. they should not appear in the search path, similar to how private behaves for classes in Java or how private functions in Matlab behave.
Is there a way and if so, how can it be done?

There is no way to make a class private in MATLAB. What you can do though, is to place it in a sub-package and it will therefore be placed in a separate namespace from the rest of your package.
+mypackage
+internal
myclass.m
If you want to remove the requirement that you type internal for all your internal functions that need access to your class, you could add a wrapper function in your private folder
+mypackage/private/myclass.m
function obj = myclass(varargin)
obj = mypackage.internal.myclass(varargin{:});
end
If you really want to restrict use of the class by anything outside of your package you could put some logic within the constructor to ensure that the calling class is a member of your package
classdef myclass < handle
methods
function self = myclass()
% Get the path to the package folder
directory = fileparts(fileparts(mfilename('fullpath')));
% Ensure that the function/class that called this was part of te toolbox
S = dbstack('-completenames');
assert(numel(S) > 1 && strfind(S(2).file, directory), ...
'Class only able to be called from the toolbox')
end
end
end
Update
As mentioned by #SamRoberts in the comments, you can also put your constructor within a method block with it's Access restricted to members of the class. You would need to specify each of the classes that you would like to be granted access
classdef myclass
methods (Access = {?mypackage.Class1, ?mypackage.Class2})
function self = myclass()
% Constructor
end
end
end

Related

Modern equivalent of the superiorto() function

I'm working on rewriting an old MATLAB package. As part of that rewrite I'm updating two classes (lets call them old_class1 and old_class2) defined using the class() function to classes defined with classdef.
The definition of old_class1 contains the line superiorto('old_class2'). This function is not allowed in a constructor defined with classdef, but I am unable to find any equivalent. How do I create functionality equivalent to superiorto() in a class defined with classdef?
superiorto is no longer available in MATLAB, but I was able to find a copy of old documentation that indicates it was used to determine which object's method was called when multiple different classes were given as function arguments. For example, given obj1=class1() and obj2=class2(), with the class1 constructor containing superiorto('class2'), would cause function(obj1,obj2) to callclass1.function, rather thanclass2.function`.
With modern classdef functionality, the same can be accomplished by setting the InferiorClasses property:
classdef (InferiorClasses = {?class2}) class1

Matlab construct of classdef with constraints

I have this
classdef what
properties ( ... )
...
end
methods (Access=public)
...
end
methods
function obj = what(...) ... end % constructor
function test = Test1() ... end
function test = Test2() ... end
end
The constructor has a lot of constraints in it such that when I create the what it fails if the conditions are not met, the constraints are tested by calling Test1 and Test2.
I have stored the test functions also under methods, and I want these to be hidden so that they don't show up outside the classdef. but I get thrown an error for Test1 and Test2.
I want these Test functions to be private, hidden, and only related to this class but I also want it to be call-able when using the constructor function found in methods, My question is: what would be the 'correct' place and method to store these functions.
I am currently getting an error when I use the constructor function, however, if I add the functions in the bottom of the page outside the classdef then the functions work but I am not sure if this is good practice and why I can't have the test functions in the method section.
There are several ways to deal with this.
In general, private functions are placed inside a methods (Access = private) block. Sometimes they can also be made static, if this makes sense. Private methods can also be placed in a separate folder.
classdef what
methods % no properties here
function obj = what(varargin) % constructor
...
out = obj.Test1(in); % object method calling example
...
end
end
methods (Access = private)
function tf = Test1(varargin)
...
end
% etc ...
end
If these functions are only ever used by the constructor, you can make them nested:
classdef what
methods % no properties here
function obj = what(varargin) % constructor
...
out = Test1(in); % no need for "obj" here
...
function tf = Test1(varargin)
...
end % Test1
end % constructor
end % methods
As mentioned by Cris, you can also put functions after the classdef block:
classdef what
...
end
function tf = Test1(varargin)
end
The suggestions above should solve your problem. Now for some other comments:
It's probably not a goot idea to name your class what, as this is a name of a builtin MATLAB function.
While it is possible to set a private method block to be Hidden, this is generally not needed in order to "hide" private methods, as these are not visible outside the class anyway.
I would personally suggest sticking to a certain naming convention (e.g. Pascal or Java) (this is referring to the class name which is lowercase as opposed to the "Test" methods which are uppercase).
If you're fairly new to MATLAB OOP, you might want to read about Handle Classes.

Load or import map for use by class instance in matlab

I have a containers.Map file/variable that I've defined through the Matlab Command Window (or some other script) and have saved it to directory. I'd like to be able to have an instance of my class be able to use that map without having to define it in the class definition, or with some other function that defines it each time the function is called. So I have:
myMap.mat
and in a separate myClass.m file (in the same directory) i'd like to be able to call myMap like so:
classdef myClass < handle
properties
number
end
methods
function obj = myClass(input)
obj.number = myMap(input);
end
end
end
What's the most efficient way to get myMap "into the class" so that the instance can use it? matfile has been giving me some Warnings about format not supporting partial loading, and I can't imagine load is terribly efficient. Any suggestions is appreciated.
There are many approaches you can use but, honestly, I think the simplest one would be using a persistent object in your class constructor, as follows:
classdef myClass < handle
properties
number
end
methods
function obj = myClass(input)
persistent pmap;
if (isempty(pmap))
load('map.mat','map');
pmap = map;
end
obj.number = pmap(input);
end
end
end

Import class to access constant values

I defined a class in one of my many MATLAB packages. To my suprise, I could not access a constant property of my class without importing the class definition. Even if it is a method of the class itself. Like so:
classdef TestClass
properties( Constant )
c=0;
end
methods
function obj = TestClass()
end
function getC(obj)
import test.TestClass;
disp(TestClass.c);
end
end
end
I just want to check whether I am doing something wrong here or is this the correct way to use constants in MATLAB.
Since you have placed TestClass inside a package Matlab needs to know where to look to find the definition for this class, even if it's a reference from within the class or function. An alternate to the above code could be:
function getC(obj)
disp(test.TestClass.c);
end
Alternately, if within a class, constant values can be accessed from the object itself.
function getC(obj)
disp(obj.c);
end
If neither of these is working for you, you may need to refresh the classdef for TestClass from memory. This will cause matlab to reload the constant value, which is pulled into Matlab when it first parses the classdef file to determine the structure of the class. This can be done using clear classes, however a warning that it will also clear all other classes, variables, and any breakpoints you have set.
If you want to see if this is necessary you can view the metaclass object to determine what Matlab "thinks" your class structure should be. You can do this using the following.
mc = ?test.TestClass;
mc.PropertyList
You may need to index into the property list to find the specific property you are interested in, but the thing you are looking for are the following fields.
Name: 'c'
Constant: 1
DefaultValue: 0

implementing abstract methods in matlab

I'm new to MATLAB OOP. I have an abstract class defining an abstract method in my matlab path. I have a subclass named SubAbsClass in a subfolder named #SubAbsClass. I cannot create an object of the subclass after implementing the abstract method in the subclass. Here's my SubAbsClass implementation:
classdef SubAbsClass < AbsClass
properties
O1
end
methods
function obj=SubAbsClass(a,b)
obj.O1=absMethod(a,b);
end
end
methods (Static)
function out = absMethod(a,b)
out = a + b;
end
end
end
and my abstract class implementation is:
classdef AbsClass
methods(Abstract, Static)
result = absMethod
end
end
when I try to create an object in the MATLAB path (the abstract class is in the MATLAB path), I get an error. I have tried many configurations and searched the matlab oop document, and also the web including stackoverflow but unfortunately couldn't find an example to implement. I appreciate your help
>> clear all; clear classes;
>> obj=SubAbsClass(5,2)
Undefined function 'absMethod' for input arguments of type 'double'.
Error in SubAbsClass (line 11)
obj.O1=absMethod(a,b);
Within a method, Matlab considers non-dot references to be calls to local functions (defined outside the classdef block within the class file) or to a function somewhere on the Matlab path following the usual look-up rules.
So you need to call the Static method via the instance obj in the constructor:
methods
function obj = SubAbsClass(a,b)
obj.O1 = obj.absMethod(a,b);
end
end
One little caveat to the above is that non-Static methods also have a functional form.
So if the method was not Static, this notation would also work
methods
function obj = SubAbsClass(a,b)
obj.O1 = absMethod(obj,a,b);
end
end
Which, I think, is almost equivalent to the dot notation, although it has been said to be "generally" faster (albeit, that was four years ago).
Here are the details for ordinary method invocation and Static method invocation.